A form that redirects to google should be easy to implement. Another simple approach, that you can do for yourself, is to add a quick search in Firefox. I have this bound to keyword 'a';
The problem with using google to search forums, however, is that it doesn't know anything about threads. When I type 'a module' in FF's location bar, I get 121 hits (should be 122 after I post this ;), and I have no idea how many threads that is - not very practical.
A problem with unquoting the function value is that if you redefine the function, any code that uses the macro will hold on to the original function as a literal. This means the solution doesn't lend itself well to exploratory programming.
Well, one could create a module system so that the macro would always see the function the way it was seen in the module where the macro was defined. Then, when the function name is rebound where the macro is applied, it doesn't affect the macro, but if the function is recompiled in its original module, it does affect the code produced by the macro. I'm not saying it's straight forward, but I do believe it's possible.
I'm sure you will remember to use foo:bar when the alternative is (fn args (foo (apply bar args)))
Using : only in the most important places might be a good thing. I.e not overuse it for (foo (bar x)) -> (foo:bar x) where it trades readability for 2 characters.
Just a follow up question on this. How do people feel about (fn ... ) not having implicit progn? That sounds extreme, I know, but it would open the door for pattern matching in the very core of Arc.
(fn (x y)
(prs "two args:" x y)
((x . xs))
(prs "a cons cell:" x xs)
args
(prs "many, many args:" args))
The more I think about this, the more mind boggling I find it. What exactly would this expression expand to?
(and (acons x) (car x) @lst)
The actual lst is only available at runtime, while the 'and macro expands at compile time.
Edit:
After looking at the definition of 'and, it is clear that the above could never work. Without performing the splice it would expand to
(if (acons x) (if (car x) @lst))
For each additional argument 'and must add another 'if to the code, so with lst being spliced in at runtime, we have an impossible problem.
It seems @ can only ever work reliably in quasiquote. I guess longtime lispers already knew, otherwise we would probably have had this feature for several decades already.
If you insist, it could still be done for functions. To avoid inefficient code, it better be smart about how it builds the list;
I had assumed that (and (acons x) (car x) @lst) would expand to (and (acons x) (car x) lst.0 lst.1 ... lst.N), and only then would it expand to (if (acons x) (if (car x) (if lst.0 ...))). In other words, @s are expanded as though they were the outermost macro, not the innermost. That should remove the problem of 'and having to be psychic. Your point about efficiency, however, is a very good one.
As mentioned, the macro expands at compile time, but the value of lst is not available until runtime.
In order to expand a call to 'and with 6 sub expressions into (if e0 (if e1 (if e2 (if e3 (if e4 e5))))), all 6 expressions must be visible at compile time.
Splicing in a list of arguments to a macro will simply never work (except by compiling the code from scratch each time you run it, i.e. limiting yourself to the most inefficient of interpreter techniques)
Aha! Oh, I see. I should have realized that. Yes, that's a problem :) I'm not convinced it's insurmountable, but this syntax certainly won't work. Thank you.
I still, however, think it might be nice for functions, but that's merely a difference in appearance, not functionality.
That means (+ . (1 2 3)) does what you want, doesn't it?
Granted, to do the equivalent of (+ @(foo)) you would have to do;
(let temp (foo)
(+ . temp))
Which is not very nice at all, so I'm not arguing against @. On the contrary.
Edit:
I used to think that . and @ would only differ in the sense that cons and splice have different list building semantics, but now I believe that they should also differ in the timing of the operation;
(+ . (foo)) -> (+ foo)
(+ . '(foo)) -> (+ quote foo)
(+ @(foo)) -> what we want, given that foo returns a list
(+ @'(foo)) -> (+ 'foo)
Keyword arguments definitely have their place. They fix a problem with having too many optional args. Example:
(def foo (a b c (o d) (o e) (o f) (o g))
If you want to call foo with g but not the other optional args, you'd have to write
(foo 1 2 3 nil nil nil 42)
It's easy to loose track of positional args when there are more than say 5 of them (depends on the person), and it gets a lot worse when some are just nils. The above call with keyword args instead of optionals would be something like;
(foo 1 2 3 'g 42)
Or, depending on the implementation, there might be a special syntax;
I think there are two distinct cases here. The first is when a procedure is taking a number of options/switches. The second is when the function has a long list of optional arguments.
I actually think the second is pretty rare, especially if the argument list is ordered by practical use. The first is handled pretty nicely by passing in association lists or hash tables. Of course, the current syntax for creating hash tables doesn't make using them as arguments super-easy, but they're the equivalent of passing a dictionary in python for kwargs, and they don't require any new syntax.
edit:
In my imagined world, your last example would look something like
I don't see the distinction between taking a number of options and having a number of optional arguments. To me, this is exactly the same. A switch is an argument that is only checked for true/false, which means that in ordinary function calls you only really want to bother with it when passing 't.
It's true that passing a data structure can do most of the job of keyword arguments. Any searchable structure will do, really. Perhaps the simplest form from the call site's point of view is a property list. If Scheme's plist-get was implemented in Arc (trivial, but pg would probably pick a shorter name):
(def foo (a b c . rest)
(plist-get rest 'g))
arc> (foo 1 2 3 'g 42)
42
So, what do keyword arguments give you that tables/alists/plists do not?
1) better self documentation - the function signature tells what keys it understands
2) less code in the function body - you access the value like any other argument
3) a default form which is only evaluated if no value was given - without adding code to the function body
When you say environment, do you mean lexical environment or global namespace? Neither is possible today, I believe, but when someone⢠writes a module system for Arc, namespaces will hopefully be right at your finger tips (if implemented as Arc tables).
Problem is, you're adding a coupling between the function and the name. No such coupling exists in any lisp that I'm aware of. Conceptually, in Scheme and Arc
(def foo (x) (prn "it's " x))
is the same as
(= foo (fn (x) (prn "it's " x)))
i.e. all functions are anonymous from their own pov.
Also, variable lookup is going to be very slow. What you're saying is that the following will make lookup of any name starting with "a" return the same value;
(= /a.*/ 42)
I'm sure lots of interesting tricks can be done with this, but I'm afraid it adds a lot of complexity only to make very confusing functions possible.
I think that there are some nice possibilities lurking in this idea. Perhaps there could be a macro defined that modifies def to use this functionality (kind of like pm:def).