Hi,

2016/7/7 Thu 20:24:45 UTC+9 Bram Moolenaar wrote:
> Nikolay Pavlov wrote:
> 
> > >> > I have mixed feelings about this implementation.  This needs more
> > >> > thoughts and discussion.
> > >> >
> > >> >
> > >> > One of the problems with the current use of a string for an expression,
> > >> > as it's passed to map(), filter(), etc., is that this is a string, 
> > >> > which
> > >> > requires taking care of quotes.
> > >> >
> > >> > Using lambda() for that doesn't have an advantage, it's only longer:
> > >> >
> > >> >         :call map(mylist, '"> " . v:val . " <"')
> > >> >         :call map(mylist, lambda('"> " . v:val . " <"'))
> > >> >
> > >> > Perhaps we can define the lambda not as a function call, but as an
> > >> > operator.  Then it will be parsed differently and we don't need to put
> > >> > the expression in quotes.  We do want to be able to define it inline, 
> > >> > as
> > >> > a function argument.  We do need something around it, so that it's 
> > >> > clear
> > >> > where the end is.  Using {} would work, it's similar to a statement
> > >> > block in most languages.
> > >> >
> > >> > We would also like to specify arguments.  We could separate the
> > >> > arguments from the statements with a "gives" symbol.  That could be ->.
> > >> > This avoid the strange use of v:val and v:key to pass values to the
> > >> > expression, like map() does.
> > >> >
> > >> >         call Func(arg, lambda{v -> return v * 3.12})
> > >> >
> > >> > That way we can do this:
> > >> >         call map(mylist, lambda{v -> return "> " . v . " <"})
> > >> >
> > >> > In most cases only one statement is needed, but having a few more 
> > >> > should
> > >> > be possible.  Using | to separate statements hopefully works:
> > >> >
> > >> >         call Func(arg, lambda{ v -> if v < 0 | return v * 3.12 | else 
> > >> > | return v * -3.12 | endif})
> > >> >
> > >> > Something like that.  If it gets too long it's better to just define a
> > >> > function.
> > >>
> > >> `lambda{ v -> if v < 0 | return v * 3.12 | else | return v * -3.12 |
> > >> endif}` is too verbose. AFAIR I already suggested lambdas
> > >> implementation once and it was just
> > >>
> > >>     \arg1, arg2 : expr1
> > >>
> > >> . I.e. lambda functions do *not* allow to use commands, only
> > >> expressions. Documentation for my attempt was
> > >
> > > Yes, that is an option.  It does restrict the situations when it can be
> > > used, but since a multi-statement lambda quickly becomes unreadable,
> > > there may not be much use for it anyway.
> > >
> > > It does require the possibility to create a closure with a nested
> > > function, in case we do need multiple statements, but if we do support
> > > closures it should be done for both lambda and normally defined
> > > functions anyway.
> > >
> > > I do not like the cryptic syntax.  I think the word "lambda" is good,
> > > unless we can think of something that is easy to recognize.
> > > One possible option is to focus on using the "gives" token:
> > >
> > >         { a1, a2 -> a1 + a2 }
> > >
> > > Even without an argument it can still be recognized:
> > >
> > >         { -> string(Today()) }
> > 
> > This is way harder to implement, `{` already defines a dictionary and
> > it may also be used for variable names, what already requires a “call
> > eval1 twice” hack. `\` has no such problem, and I do not see this too
> > cryptic. If you think that `->` is necessary, it is better to prefer
> > `\args -> expr1` over `\args : expr1`, not `{ args -> expr1 }`.
> > 
> > Prefixing lambda with `lambda` keyword makes this easy, but way too verbose.
> 
> I do think that the backslash (or any other special character that might
> be available) makes it ugly.
> 
> Although we can find the end of the expression without the "}", mistakes
> will be very hard to figure out.  Also reading back a lambda that's
> passed as an agument to a function with many arguments will make the {}
> part easy to spot.  I have done this in Zimbu and I'm happy with how it
> looks.
> 
> I don't think it's hard to implement: When finding a "{" look forward,
> skipping over [a-zA-Z0-9 ], if "->" is found it's a lambda.

Here is an experimental patch:

https://bitbucket.org/k_takata/vim-ktakata-mq/src/90ea467da862bc2eaf59454f75b8faea34604a1e/lambda2.patch?fileviewer=file-view-default

* Support only one expression.
* The "a:" prefix cannot be omitted.
* No closures.
* Inefficient "{" parser.

Both mattn's patch and ZyX's code are partly used.
Nested lambdas are also supported like ZyX's example:

  :echo {a -> {tmp -> [a:tmp, a:tmp + 2, a:tmp + 5]}(a:a * 5)}(2)
  [10, 12, 15]

Hmm, it's hard to read.


BTW, I googled lambda expressions in some other languages.

Python:
  lambda args: expr

Ruby:
  lambda{ |args| ... }

Java:
  (args) -> ...

JavaScript
  (args) => { statements }
  (args) => expr

C++:
  [](args){ ... }

Haskell:
  \args -> expr

Scala:
  (args) => expr


Regards,
Ken Takata

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Raspunde prin e-mail lui