* Shorter lambda expressions @ 2014-01-23 4:51 Mark H Weaver 2014-01-23 7:17 ` Mateusz Kowalczyk ` (2 more replies) 0 siblings, 3 replies; 9+ messages in thread From: Mark H Weaver @ 2014-01-23 4:51 UTC (permalink / raw) To: guile-devel [-- Attachment #1: Type: text/plain, Size: 1446 bytes --] Hello all, For a short time I liked 'cut' from SRFI-26, but I soon became frustrated by its limitations, most notably not being able to reference the arguments out of order or within nested expressions. I don't like the inconsistent style that results when I use 'cut' wherever possible and 'lambda' everywhere else. So I just stopped using it altogether. I prefer what Shiro Kawai did in Gauche: ^ is short for lambda, (^x ...) is short for (lambda (x) ...), and similarly for all the letters. ^_ is short for lambda with one ignored argument. http://blog.practical-scheme.net/gauche/20100428-shorter-names Here's a module that implements that idea, but takes it slightly further. It exports the unary lambda shorthands described above, and also a few non-unary ones: ^xy, ^xyz, ^ab, ^abc, ^uv. It also exports variants that use λ instead of ^, for a nicer look if you're willing to venture outside of ASCII. Finally, it exports the transformer procedure that's bound to all of the keywords above. It's called 'short-lambda'. Bind it to any keyword like this: (define-syntax ^kw short-lambda) and now (^kw ...) will expand to (lambda (k w) ...). 'short-lambda' splits the keyword into individual characters. The first character (usually ^ or λ) is ignored. The other characters become the variable names. Underscores are treated specially: they become gensyms. Thoughts? Mark [-- Attachment #2: Short lambdas for Guile --] [-- Type: text/plain, Size: 1460 bytes --] (define-module (ice-9 short-lambdas) #:export (^ ^_ λ_ ^a ^b ^c ^d ^e ^f ^g ^h ^i ^j ^k ^l ^m ^n ^o ^p ^q ^r ^s ^t ^u ^v ^w ^x ^y ^z ^xy ^xyz ^ab ^abc ^uv λa λb λc λd λe λf λg λh λi λj λk λl λm λn λo λp λq λr λs λt λu λv λw λx λy λz λxy λxyz λab λabc λuv short-lambda)) (eval-when (expand) (define short-lambda (lambda (form) (syntax-case form () ((k-id body0 body ...) (let* ((k-symbol (syntax->datum #'k-id)) (k-name (symbol->string k-symbol)) (chars (cdr (string->list k-name))) (names (map string chars)) (symbols (map string->symbol names))) (define (sym->id sym) (case sym ((_) (car (generate-temporaries '(_)))) (else (datum->syntax #'k-id sym)))) (with-syntax ((ids (map sym->id symbols))) #'(lambda ids body0 body ...)))))))) (define-syntax-rule (define-short-lambdas k ...) (begin (define-syntax k short-lambda) ...)) (define-short-lambdas ^ ^_ λ_ ^a ^b ^c ^d ^e ^f ^g ^h ^i ^j ^k ^l ^m ^n ^o ^p ^q ^r ^s ^t ^u ^v ^w ^x ^y ^z ^xy ^xyz ^ab ^abc ^uv λa λb λc λd λe λf λg λh λi λj λk λl λm λn λo λp λq λr λs λt λu λv λw λx λy λz λxy λxyz λab λabc λuv) ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: Shorter lambda expressions 2014-01-23 4:51 Shorter lambda expressions Mark H Weaver @ 2014-01-23 7:17 ` Mateusz Kowalczyk 2014-01-23 8:17 ` Panicz Maciej Godek 2016-09-23 16:44 ` Panicz Maciej Godek 2 siblings, 0 replies; 9+ messages in thread From: Mateusz Kowalczyk @ 2014-01-23 7:17 UTC (permalink / raw) To: guile-devel On 23/01/14 04:51, Mark H Weaver wrote: > Hello all, > > For a short time I liked 'cut' from SRFI-26, but I soon became > frustrated by its limitations, most notably not being able to reference > the arguments out of order or within nested expressions. I don't like > the inconsistent style that results when I use 'cut' wherever possible > and 'lambda' everywhere else. So I just stopped using it altogether. > > I prefer what Shiro Kawai did in Gauche: ^ is short for lambda, (^x ...) > is short for (lambda (x) ...), and similarly for all the letters. ^_ is > short for lambda with one ignored argument. > > http://blog.practical-scheme.net/gauche/20100428-shorter-names > > Here's a module that implements that idea, but takes it slightly > further. It exports the unary lambda shorthands described above, and > also a few non-unary ones: ^xy, ^xyz, ^ab, ^abc, ^uv. It also exports > variants that use λ instead of ^, for a nicer look if you're willing to > venture outside of ASCII. > > Finally, it exports the transformer procedure that's bound to all of the > keywords above. It's called 'short-lambda'. Bind it to any keyword > like this: > > (define-syntax ^kw short-lambda) > > and now (^kw ...) will expand to (lambda (k w) ...). > > 'short-lambda' splits the keyword into individual characters. The first > character (usually ^ or λ) is ignored. The other characters become the > variable names. Underscores are treated specially: they become gensyms. > > Thoughts? > > Mark > > Hi, Any chance for the curried version of these? -- Mateusz K. ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: Shorter lambda expressions 2014-01-23 4:51 Shorter lambda expressions Mark H Weaver 2014-01-23 7:17 ` Mateusz Kowalczyk @ 2014-01-23 8:17 ` Panicz Maciej Godek 2014-01-24 10:54 ` Ludovic Courtès 2016-09-23 16:44 ` Panicz Maciej Godek 2 siblings, 1 reply; 9+ messages in thread From: Panicz Maciej Godek @ 2014-01-23 8:17 UTC (permalink / raw) To: Mark H Weaver; +Cc: guile-devel Hi! 2014/1/23 Mark H Weaver <mhw@netris.org>: > Hello all, > > For a short time I liked 'cut' from SRFI-26, but I soon became > frustrated by its limitations, most notably not being able to reference > the arguments out of order or within nested expressions. I don't like > the inconsistent style that results when I use 'cut' wherever possible > and 'lambda' everywhere else. So I just stopped using it altogether. [...] Before getting acquainted with SRFI-26, I came up with something similar. It uses define-macro, because I didn't know syntax-case back then, but I eventually stopped using it, since it was a little bit confusing. It solved the problem by allowing numbered placeholders, so e.g. (\ + _1 _10) created a function of ten arguments which added its first argument to its tenth argument, skipping all the others. There was also a general placeholder, _, which behaved like SRFI-26's <>, so for instance (\ + _ _) was an equivalent of (\ + _1 _2) but I eventually started to find it a little confusing, because the same symbol refered to another entity. Also the choice of symbol "\" was unfortunate, as it made the syntax unportable among schemes (certain implementations would require to write "\\" to get a backslash). As far as I remember (I'd have to analyze the code to make sure), it did support nested expressions. Also, after some time, I added another placeholder ... for variadic arguments, which behaved more or less like <...> form SRFI-26. I think it would be best to extend SRFI-26 with the option of using <1>, <2>, ... placeholders, where the resulting lambda would get the arity indicated by the highest placeholder. Also, it should support nested expressions. Personally, I'd prefer it over the Gauche-style extension. (define-macro (\ f . args) (let* ((prefix "_") (placeholder '_) (ellipsis '...) (rest (if (equal? (last args) ellipsis) ellipsis '())) (args (if (symbol? rest) (drop-right args 1) args)) (max-arg 0) (next-arg (lambda () (set! max-arg (+ max-arg 1)) (string->symbol (string-append prefix (number->string max-arg)))))) (letrec ((process-arg (lambda(arg) (cond ((eq? arg placeholder) (next-arg)) ((and-let* (((symbol? arg)) (arg-string (symbol->string arg)) (match-struct (string-match (string-append "^" (regexp-quote prefix) "([0-9]+)$") arg-string)) (number (string->number (match:substring match-struct 1)))) (if (> number max-arg) (set! max-arg number)) #t) arg) ((and (list? arg) (not (null? arg)) (not (memq (first arg) '(\ quote)))) (map process-arg arg)) (else arg))))) (let ((args (map process-arg args))) `(lambda ,(append (map (lambda (n) (string->symbol (string-append prefix (number->string n)))) (iota max-arg 1)) rest) ,(if (symbol? rest) `(apply ,f ,@args ,rest) `(,f ,@args))))))) ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: Shorter lambda expressions 2014-01-23 8:17 ` Panicz Maciej Godek @ 2014-01-24 10:54 ` Ludovic Courtès 2014-01-24 11:28 ` Taylan Ulrich Bayırlı/Kammer 0 siblings, 1 reply; 9+ messages in thread From: Ludovic Courtès @ 2014-01-24 10:54 UTC (permalink / raw) To: guile-devel Panicz Maciej Godek <godek.maciek@gmail.com> skribis: > I think it would be best to extend SRFI-26 with the option of using > <1>, <2>, ... placeholders, where the resulting lambda would get the > arity indicated by the highest placeholder. Also, it should support > nested expressions. > Personally, I'd prefer it over the Gauche-style extension. I think I’d prefer this too, but actually I’m mostly satisfied with SRFI-26. One related thing I sometimes lack is: (define-syntax-rule (thunk exp ...) (lambda () exp ...)) (Found in Racket, notably.) Ludo’. ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: Shorter lambda expressions 2014-01-24 10:54 ` Ludovic Courtès @ 2014-01-24 11:28 ` Taylan Ulrich Bayırlı/Kammer 2014-01-24 16:09 ` Mark H Weaver 0 siblings, 1 reply; 9+ messages in thread From: Taylan Ulrich Bayırlı/Kammer @ 2014-01-24 11:28 UTC (permalink / raw) To: Ludovic Courtès; +Cc: guile-devel ludo@gnu.org (Ludovic Courtès) writes: > One related thing I sometimes lack is: > > (define-syntax-rule (thunk exp ...) > (lambda () exp ...)) My understanding is that that'd be (^ exp ...). `thunk' might be nicer for one's tastes, but some consistency between different people's code would be desired, so let me recommend sticking to ^ because: * It's 4 characters shorter, which is a whole 1/20 (5%) of 80 columns! * It's consistent with all the ^x etc. I'm not entirely serious about the first point, though I do desire consistency between people's code. :-) Taylan ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: Shorter lambda expressions 2014-01-24 11:28 ` Taylan Ulrich Bayırlı/Kammer @ 2014-01-24 16:09 ` Mark H Weaver 0 siblings, 0 replies; 9+ messages in thread From: Mark H Weaver @ 2014-01-24 16:09 UTC (permalink / raw) To: Taylan Ulrich "Bayırlı/Kammer" Cc: Ludovic Courtès, guile-devel [-- Attachment #1: Type: text/plain, Size: 776 bytes --] taylanbayirli@gmail.com (Taylan Ulrich "Bayırlı/Kammer") writes: > ludo@gnu.org (Ludovic Courtès) writes: > >> One related thing I sometimes lack is: >> >> (define-syntax-rule (thunk exp ...) >> (lambda () exp ...)) > > My understanding is that that'd be (^ exp ...). That's true given the code I posted, but it was not intentional. I meant to follow Gauche's convention that '^' is an alias for 'lambda', so you'd need to type (^() exp ...) instead. Another bug is that I should have used (expand load eval) in the 'eval-when'. Finally, I've decided that it's nicer to export 'define-short-lambda' than 'short-lambda'. Here's an updated version. More thoughts? Alas, I guess this entire topic is bikeshed territory :) Mark [-- Attachment #2: Short lambdas for Guile v2 --] [-- Type: text/plain, Size: 1636 bytes --] (define-module (ice-9 short-lambdas) #:export (^ ^_ λ_ ^a ^b ^c ^d ^e ^f ^g ^h ^i ^j ^k ^l ^m ^n ^o ^p ^q ^r ^s ^t ^u ^v ^w ^x ^y ^z ^xy ^xyz ^ab ^abc ^uv λa λb λc λd λe λf λg λh λi λj λk λl λm λn λo λp λq λr λs λt λu λv λw λx λy λz λxy λxyz λab λabc λuv define-short-lambda)) (eval-when (expand load eval) (define short-lambda (lambda (form) (syntax-case form () ((k-id body0 body ...) (let* ((k-symbol (syntax->datum #'k-id)) (k-name (symbol->string k-symbol)) (chars (cdr (string->list k-name))) (names (map string chars)) (symbols (map string->symbol names))) (define (sym->id sym) (case sym ((_) (car (generate-temporaries '(_)))) (else (datum->syntax #'k-id sym)))) (with-syntax ((ids (map sym->id symbols))) #'(lambda ids body0 body ...)))))))) (define-syntax-rule (define-short-lambda k) (define-syntax k short-lambda)) (define-syntax-rule (define-short-lambdas k ...) (begin (define-short-lambda k) ...)) (define-syntax-rule (^ formals body0 body ...) (lambda formals body0 body ...)) (define-short-lambdas ^_ λ_ ^a ^b ^c ^d ^e ^f ^g ^h ^i ^j ^k ^l ^m ^n ^o ^p ^q ^r ^s ^t ^u ^v ^w ^x ^y ^z ^xy ^xyz ^ab ^abc ^uv λa λb λc λd λe λf λg λh λi λj λk λl λm λn λo λp λq λr λs λt λu λv λw λx λy λz λxy λxyz λab λabc λuv) ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: Shorter lambda expressions 2014-01-23 4:51 Shorter lambda expressions Mark H Weaver 2014-01-23 7:17 ` Mateusz Kowalczyk 2014-01-23 8:17 ` Panicz Maciej Godek @ 2016-09-23 16:44 ` Panicz Maciej Godek 2016-09-24 9:38 ` Panicz Maciej Godek 2 siblings, 1 reply; 9+ messages in thread From: Panicz Maciej Godek @ 2016-09-23 16:44 UTC (permalink / raw) To: guile-devel [-- Attachment #1: Type: text/plain, Size: 797 bytes --] I hope you don't mind me having dug this thread up, with an idea that is only loosely related with the original one. Recently I've been doing a small project in Clojure, and I've found that it provides a function called "partial" that performs a sort of partial application. With guile's curried definitions, it can be defined as (define ((partial function . args) . args+) (apply function `(,@args ,@args+))) and it works rather nicely: (map (partial cons 2) '((3 4) (3 5) (4 6) (7 1))) ===> ((2 3 4) (2 3 5) (2 4 6) (2 7 1)) I believe that -- since it is just a function -- it is much less controversial than both the short macros and SRFI-26 (although its range of applicability is narrower), and it seems to compose well with the spirit of Scheme, so maybe that would be a nice-have? [-- Attachment #2: Type: text/html, Size: 977 bytes --] ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: Shorter lambda expressions 2016-09-23 16:44 ` Panicz Maciej Godek @ 2016-09-24 9:38 ` Panicz Maciej Godek 0 siblings, 0 replies; 9+ messages in thread From: Panicz Maciej Godek @ 2016-09-24 9:38 UTC (permalink / raw) To: guile-devel [-- Attachment #1: Type: text/plain, Size: 1697 bytes --] 2016-09-23 18:44 GMT+02:00 Panicz Maciej Godek <godek.maciek@gmail.com>: > I hope you don't mind me having dug this thread up, with an idea that is > only loosely related with the original one. > > Recently I've been doing a small project in Clojure, and I've found that > it provides a function called "partial" that performs a sort of partial > application. > > With guile's curried definitions, it can be defined as > > (define ((partial function . args) . args+) > (apply function `(,@args ,@args+))) > > and it works rather nicely: > > (map (partial cons 2) '((3 4) (3 5) (4 6) (7 1))) > ===> ((2 3 4) (2 3 5) (2 4 6) (2 7 1)) > > I believe that -- since it is just a function -- it is much less > controversial than both the short macros and SRFI-26 (although its range > of applicability is narrower), and it seems to compose well with the spirit > of Scheme, so maybe that would be a nice-have? > I take it back. It is a terrible idea. Using explicit lambda is a better solution, because it gives an opportunity to provide a name for an element of a list. Yet the name "partial" reads terribly. Compound usages such as (partial map (partial cons 1)) are much worse than their regular counterparts, i.e. (lambda (list) (map (lambda (element) (cons 1 element)) list)) because even though the latter are more lengthy, this length actually serves the purpose of exposing the structure of expression. In the former case, it isn't clear (without knowing the arity of map) what will be the arity of the whole expression, nor the role of those arguments. It seems to be a problem even in the case of well-known functions such as cons or map. Sorry for the noise [-- Attachment #2: Type: text/html, Size: 2442 bytes --] ^ permalink raw reply [flat|nested] 9+ messages in thread
[parent not found: <201401241138.s0OBc9u5025102@lambda.ccs.neu.edu>]
* Re: Shorter lambda expressions [not found] <201401241138.s0OBc9u5025102@lambda.ccs.neu.edu> @ 2014-01-24 13:28 ` Eli Barzilay 0 siblings, 0 replies; 9+ messages in thread From: Eli Barzilay @ 2014-01-24 13:28 UTC (permalink / raw) To: ludo > One related thing I sometimes lack is: >=20 > (define-syntax-rule (thunk exp ...) > (lambda () exp ...)) >=20 > (Found in Racket, notably.) IMO, it's much more useful to have `λ', together with an Emacs hack that makes it easy to type. In the last few years I even switched to omitting the space in some simple cases, so I use (λ() (blah) (blah) (blah)) which is even shorter than `thunk'. Also, there's no confusion between `thunk' and `thunk*' (accepts any number of arguments) which some people prefer. (Not on the list; feel free to forward...) -- ((lambda (x) (x x)) (lambda (x) (x x))) Eli Barzilay: http://barzilay.org/ Maze is Life! ^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2016-09-24 9:38 UTC | newest] Thread overview: 9+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2014-01-23 4:51 Shorter lambda expressions Mark H Weaver 2014-01-23 7:17 ` Mateusz Kowalczyk 2014-01-23 8:17 ` Panicz Maciej Godek 2014-01-24 10:54 ` Ludovic Courtès 2014-01-24 11:28 ` Taylan Ulrich Bayırlı/Kammer 2014-01-24 16:09 ` Mark H Weaver 2016-09-23 16:44 ` Panicz Maciej Godek 2016-09-24 9:38 ` Panicz Maciej Godek [not found] <201401241138.s0OBc9u5025102@lambda.ccs.neu.edu> 2014-01-24 13:28 ` Eli Barzilay
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).