[racket] Splicing `values' in-place

From: Jay McCarthy (jay.mccarthy at gmail.com)
Date: Sat Jul 13 10:10:37 EDT 2013

I just wrote a blog post about this code, in case it is unclear how it works

http://jeapostrophe.github.io/2013-07-15-values-post.html

On Fri, Jul 12, 2013 at 1:07 AM, Stephan Houben <stephanh42 at gmail.com> wrote:
> I am deeply impressed.
>
> Python's Guido van Rossum is often suspected of owning a time machine,
> but apparently you have one too...
>
>
>
>
> 2013/7/11 Jay McCarthy <jay.mccarthy at gmail.com>
>>
>> On Thu, Jul 11, 2013 at 1:52 PM, Stephan Houben <stephanh42 at gmail.com>
>> wrote:
>> > Hi Jay,
>> >
>> > So what about keyword return values?
>> > Both because of symmetry and because getting three return values
>> > straight is
>> > just as hard as getting three arguments straight.
>>
>> That's old news:
>>
>> https://github.com/jeapostrophe/exp/blob/master/values.ss
>>
>> FWIW, keywords aren't built-in in Racket for function calls, so this
>> approach to them in function returns *is* symmetric.
>>
>> Jay
>>
>> > Stephan Houben
>> >
>> > Op 11 jul. 2013 21:39 schreef "Jay McCarthy" <jay.mccarthy at gmail.com>
>> > het
>> > volgende:
>> >
>> >> I prefer to think of values as being justified by not restricting the
>> >> arity of continuations.
>> >>
>> >> (let/cc k
>> >>  (k 1 2 3))
>> >>
>> >> (let/cc k
>> >>  (k))
>> >>
>> >> etc.
>> >>
>> >> define-values & let-values create N-arity continuations whereas
>> >> call-with-values creates an any arity context
>> >>
>> >> Jay
>> >>
>> >>
>> >> On Thu, Jul 11, 2013 at 12:23 PM, Laurent <laurent.orseau at gmail.com>
>> >> wrote:
>> >> > Ah that unfortunately explains a lot. Thank you Matthew for this
>> >> > explanation.
>> >> > It's too bad that one needs to throw away nice semantics for speed...
>> >> >
>> >> > Neil's macro idea may then well be one of the best intermediate
>> >> > solutions
>> >> > then.
>> >> >
>> >> > Jens, thanks for all the links, they are quite informative.
>> >> > Indeed, quite a number of people seem unhappy with `values'.
>> >> >
>> >> > However, since I did not find an answer for the following, I will
>> >> > risk
>> >> > this
>> >> > anyway:
>> >> > Then why not return lists instead of values? Performance problem
>> >> > again?
>> >> > There would not be such a thing as "multiple return values" though,
>> >> > and
>> >> > one
>> >> > should not see them this way.
>> >> > Several values returned in a list is just a list, i.e., a single
>> >> > return
>> >> > value. Then there are helpers to bind several values from a list,
>> >> > etc.
>> >> > No need for `apply-values' or `call-with-values', just use `apply'.
>> >> > Therefore returning `(list 1)' would of course be different from
>> >> > returning
>> >> > `1', but if you don't see them as multiple return values, it's not
>> >> > inconsistent.
>> >> > The type of the procedure  would tell what is returned anyway.
>> >> > Some languages like Python, PHP (and Matlab?) do that, and I find
>> >> > this
>> >> > more
>> >> > convenient than `values'.
>> >> > A "problem" would then be quieter errors for multiple/single value
>> >> > mismatch,
>> >> > but I don't really see this one as important.
>> >> > I also don't see the need for a different data type like `sequences'
>> >> > as
>> >> > they
>> >> > call it in Jen's thread.
>> >> >
>> >> > When I use `values', either I (have to) bind them directly to
>> >> > identifiers,
>> >> > or I turn them into a list of values to manipulate them otherwise.
>> >> > The above would make this much easier and simpler I suspect.
>> >> >
>> >> > Laurent
>> >> >
>> >> >
>> >> >
>> >> >
>> >> > On Thu, Jul 11, 2013 at 5:18 PM, Matthew Flatt <mflatt at cs.utah.edu>
>> >> > wrote:
>> >> >>
>> >> >> To elaborate on "currently not possible" (because this idea shows up
>> >> >> from time to time), allowing splicing of results in function-call
>> >> >> subexpressions would break equivalences that are currently exploited
>> >> >> by
>> >> >> macros and the compiler.
>> >> >>
>> >> >> For example, many macros assume that
>> >> >>
>> >> >>  (rator rand1 rand2 ... randn)
>> >> >>
>> >> >> can be rewritten as
>> >> >>
>> >> >>  (let ([r rator]
>> >> >>        [a1 rand1]
>> >> >>        [a2 rand2]
>> >> >>        ...
>> >> >>        [an randn])
>> >> >>    (r a1 a2 ... an))
>> >> >>
>> >> >> That would not be the case if the `rand's can produce multiple
>> >> >> values.
>> >> >> (I assume that you don't want to allow binding multiple values to a
>> >> >> variable in `let'.) I think that disallowing this kind of
>> >> >> transformation would make many macros more difficult to implement
>> >> >> ---
>> >> >> and maybe impossible, in some cases.
>> >> >>
>> >> >> The Racket compiler takes advantage of transformations like the one
>> >> >> above to speed up your code. Although the compiler could still
>> >> >> perform
>> >> >> transformations when the relevant subexpressions are known to be
>> >> >> single-valued, I think the transformations would apply much less
>> >> >> often
>> >> >> than now.
>> >> >>
>> >> >> Along similar lines, various tools can tell statically you that
>> >> >>
>> >> >>  (cons e1 e2 e3)
>> >> >>
>> >> >> will be an arity error (assuming that `cons' is the usual binding).
>> >> >> That kind of support would become much weaker, since `e2' might
>> >> >> return
>> >> >> zero values while `e1' and `e3' return a single value.
>> >> >>
>> >> >> In short, the kind of splicing that you suggest is a significant
>> >> >> sense
>> >> >> more "dynamic" than Racket. You could always embed such a dynamic
>> >> >> language in Racket. Due to macros, however, I don't think it would
>> >> >> work
>> >> >> to re-interpret our existing code as being written in that language.
>> >> >> And due to the extra constraints on the compiler and run-time
>> >> >> system,
>> >> >> I'm certain that it would perform worse than Racket. Overall, my
>> >> >> sense
>> >> >> is that the potential extra convenience of splicing values is not
>> >> >> worth
>> >> >> the costs.
>> >> >>
>> >> >> At Thu, 11 Jul 2013 10:42:52 -0400, Matthias Felleisen wrote:
>> >> >> >
>> >> >> > Your uses of values are covered in apply/map/append/list
>> >> >> > trickeries.
>> >> >> > Using
>> >> >> > values might be more elegant, but yes, it's currently not
>> >> >> > possible.
>> >> >> >
>> >> >> >
>> >> >> >
>> >> >> > On Jul 11, 2013, at 8:56 AM, Laurent wrote:
>> >> >> >
>> >> >> > > In some postfix languages, if a procedure returns multiple
>> >> >> > > values,
>> >> >> > > these
>> >> >> > values can be used directly as multiple arguments to another
>> >> >> > procedure
>> >> >> > call,
>> >> >> > i.e., they are "spliced" in the latter call.
>> >> >> > > In an extended Racket, this would look like this:
>> >> >> > >
>> >> >> > > (+ (values 1 2) (values 3 4))
>> >> >> > > would be equivalent to
>> >> >> > > (+ 1 2 3 4)
>> >> >> > >
>> >> >> > > (map values '(0 1 2) '(a b c))
>> >> >> > > would return
>> >> >> > > '(0 a 1 b 2 c)
>> >> >> > >
>> >> >> > > (call-with-values (lambda()(my-proc ....)) list)
>> >> >> > > would simply be
>> >> >> > > (list (my-proc ....))
>> >> >> > >
>> >> >> > > (values (values 1 2) (values 'a 'b))
>> >> >> > > would be equivalent to
>> >> >> > > (values 1 2 'a 'b)
>> >> >> > >
>> >> >> > > Correct me if I'm wrong, but I think all the cases where this
>> >> >> > > feature
>> >> >> > > should
>> >> >> > be useful currently throws an error, so it would probably break
>> >> >> > only
>> >> >> > very
>> >> >> > little.
>> >> >> > >
>> >> >> > > Such a missing feature tickles me from time to time, and I often
>> >> >> > > find
>> >> >> > > that
>> >> >> > Racket `values' system is too cumbersome to be used more often,
>> >> >> > i.e.,
>> >> >> > you need
>> >> >> > to go through stages of `call-with-values', 'let/define-values',
>> >> >> > `(apply
>> >> >> > values
>> >> >> > ....)', etc. and I often find myself not wanting to go down this
>> >> >> > road.
>> >> >> > >
>> >> >> > > IMO, `values' is *meant* to be the way I describe above:
>> >> >> > > `values'
>> >> >> > > is
>> >> >> > > exactly
>> >> >> > like `list', except than instead of encapsulating the values in a
>> >> >> > container, it
>> >> >> > splices them in-place.
>> >> >> > >
>> >> >> > > Do you see some disadvantages of using values this way?
>> >> >> > > For example, in some occasions, for things like
>> >> >> > > (define (foo x) (values x x))
>> >> >> > > (map + (foo '(1 2 3)))
>> >> >> > > it may be more difficult to infer that there are actually 2
>> >> >> > > lists
>> >> >> > > in
>> >> >> > > the map,
>> >> >> > but to me it's just a matter of
>> >> >> > style/taste/comments/documentation,
>> >> >> > not
>> >> >> > a
>> >> >> > matter of feature.
>> >> >> > >
>> >> >> > > Laurent
>> >> >> > > ____________________
>> >> >> > >  Racket Users list:
>> >> >> > >  http://lists.racket-lang.org/users
>> >> >> >
>> >> >> >
>> >> >> >
>> >> >> >
>> >> >> >
>> >> >> > ------------------------------------------------------------------------------
>> >> >> > [application/pkcs7-signature "smime.p7s"] [~/Desktop & open]
>> >> >> > [~/Temp
>> >> >> > &
>> >> >> > open]
>> >> >> > ____________________
>> >> >> >   Racket Users list:
>> >> >> >   http://lists.racket-lang.org/users
>> >> >
>> >> >
>> >> >
>> >> > ____________________
>> >> >   Racket Users list:
>> >> >   http://lists.racket-lang.org/users
>> >> >
>> >>
>> >>
>> >>
>> >> --
>> >> Jay McCarthy <jay at cs.byu.edu>
>> >> Assistant Professor / Brigham Young University
>> >> http://faculty.cs.byu.edu/~jay
>> >>
>> >> "The glory of God is Intelligence" - D&C 93
>> >> ____________________
>> >>   Racket Users list:
>> >>   http://lists.racket-lang.org/users
>>
>>
>>
>> --
>> Jay McCarthy <jay at cs.byu.edu>
>> Assistant Professor / Brigham Young University
>> http://faculty.cs.byu.edu/~jay
>>
>> "The glory of God is Intelligence" - D&C 93
>
>



-- 
Jay McCarthy <jay at cs.byu.edu>
Assistant Professor / Brigham Young University
http://faculty.cs.byu.edu/~jay

"The glory of God is Intelligence" - D&C 93

Posted on the users mailing list.