as a lisp noob i'm curious what specific sorts of things you could do with first-class macros. perhaps swapping out macros for a given macro call? say in one pass of a program (function) a particular macro call is expanded by macro1, and in the second pass the macro call is expanded by macro2
I'm not exactly an expert on this, but I think it would allow you to put a macro literal in functional position. Right now:
arc> and
#3(tagged mac #<procedure>)
arc> (eval (list and 1 nil 2))
Error: "Bad object in expression #3(tagged mac #<procedure>)"
So if you had theoretical first-class macros, you could do stuff like use backquote to protect a macro you use from being overridden. (This wouldn't be necessary if we had a module system, but that might require first-class macros itself.) So in the (contrived) example below, foo works fine because prs is a function, but bar fails because foo is a macro.
EDIT: Actually, function literals in functional position only works on Anarki. It might be nice to have that fix in the official version.
arc> (mac foo args `(,prs ,@args))
#3(tagged mac #<procedure>)
arc> (mac bar args `(,foo ,@(keep [isa _ 'sym] args)))
#3(tagged mac #<procedure>)
I think first-class macros might be useful in making infix math expansion occur at compile time rather than run time... but I'm not completely sure on that one.
Yes, please. First class macros and the ability to use macros and functions (rather than just their names or definitions) in functional position would be great, and macro names would not have to shadow variable names gobally anymore. In my opinion that is one of the biggest problems with Arc.
i love Lua's tables. after using them, other languages feel abstruse in that department, with all these alternatives that are in my mind conceptually and functionally the same thing: (key,value) pairs
[edit]it should be noted that Lua is fast, like the fastest scripting language fast
i tried to make vim switch to a copied lisp syntax when it boots up an arc file but i wasn't able to get even that working
as far as details for the syntax, i would say don't give the [... _ ...] notation any special color or anything
once you have something, anything really, i think it would be fine if you uploaded it to the anarki arc git wiki
http://git.nex-3.com/arc-wiki.git into the 'extras' folder
personally i don't see why the insistence on a remainder-style curry. i like what i proposed in the other thread http://arclanguage.org/item?id=3962 which is that if a function is given _ as an argument, even in multiple places, then the function will be curried for those argument slots
the benefit is you don't require what i think is a somewhat arbitrary arrangement of placing the most important arguments at the end, and you don't need to use argument-swapping functions just to line things up correctly. you just put the _ into the argument spots you want to postpone and you're done
actually i don't understand any of that ^_^;; i'm a lisp noob. in other languages there aren't macros so i implement it as a function which stores the function-to-be-curried and its initial arguments in a closure
however i tested your macro with some arithmetic and it all seems to work fine. the only thing i found is that something like this will cause an error:
((fix + _ 2) 3 4)
because there isn't an underscore at the end. i don't understand lisp enough to see if that was your intention. i think for the sake of variadic functions it should adapt regardless of where the underscore is (or whether or not it's present, eg: (fix +)), either by detecting if a function is variadic (which i'm guessing isn't reasonably possible at the moment) or by always returning a variadic function [edit: actually i think i can decipher the meaning of (if (is '_ (last rest))]
if the generated expression is always variadic, it would seem to mess with the fact that the underlying system cares how many arguments there are. is that a big deal? i don't think so. a language i use this function in is Lua, whose functions are all variadic (in that the interpreter doesn't complain if you supply too few (unsupplied are niled) or too many (excess are discarded) arguments) and it simply is never a problem. to me the fixed-argument thing seems similar in spirit to static typing in that it tries to solve a problem that really isn't significant
Yes, I implemented it so it would only be variadic if there was an underscore at the end. It would actually be a simpler macro if they were always variadic, but that's such a radical change to the language that I'm a bit wary about it.
But maybe it's a good idea. I see your point about the 'spirit of static typing'. I'll have to check out Lua and see how it works out.
Edit: I mean it would be radical if fix were implicit, of course.
in other languages i write a function that i call fix which does the same as the _ notation except that the _ represents a general "hole to be filled later" and can be present any number of times
take for example a function named 'print' which accepts string, r, g, and b arguments
(= my-prn (fix print "message" _ _ _))
so that
(my-prn 0 0 1)
would print "message" in blue
(= my-prn (fix print _ 0 _ 0))
(my-prn "test" 1)
would print "test" in green. if built into the language it could be done something like:
I'm no lawyer and I haven't read the artistic license very closely, but Anarki's under the same license as the original codebase, so I'm pretty sure there shouldn't be a problem...
Well I don't think it's ugly, but ugliness aside it's very descriptive in one char. I'd personally like to see this convention carried over. Ruby uses the same convention so it's not just Scheme.
If this was intentionally left out my guess would be that PG was trying to save those chars for something meaningful to the compiler (syntax) not for aesthetics.
It should be possible to detect, at define-time, whether a function/macro has side-effects (see the ideas for a conservative purity analyzer in http://arclanguage.org/item?id=558).
So if the function/macro has side-effects, def/mac could e.g. also assign it to a second symbol with "!" appended.
'?' could also be done similarly, but would be more difficult. Here is a start:
def/mac should also assign its function/macro to a second symbol with "?" appended if:
1) The function/macro has no side-effects (no "!")
Leaving aside the issues of detecting a query, I think it's a really bad idea to have the compiler force (badly guessed) semantic knowledge on me.
It's my code, I wrote it, and I don't want any compiler telling me that a query that caches previous results must be imperative! and not end in a ? .
I also thing needlessly polluting a namespace with addition symbols is a bad idea. You only get one namespace in arc, try to preserve it for the future.
that makes sense. '!' is already being used (though the convention doesn't interfere with the syntax at the moment)
bear with me here, but '!' means the function isn't pure, right? if so, who cares? it seems like an ivory tower thing. ? is fine, though maybe prefix notation can be considered
Just because something is academic doesn't mean it's not worthwhile. For instance, map, keep, reduce, etc. are different if passed a function with side-effects. What happens if you give them a function which modifies the list as it's being traversed? A pathological example:
However, if map is passed a pure function, you can e.g. run one copy of the function on each core and run it in parallel.
And "dangerSet" is both non-Lispy and non-Arcy. It's non-Arcy because it's long. And it's non-Lispy because of that capital letter: danger-set would be marginally better. But nevertheless, pair? is shorter than is-pair, and (in my opinion) reads much more nicely.
Both nil and (len str) work. I see both sides of the argument as counting from -1 eliminates the 0 corner case.
I like indices that are intuitive with literal numbers. Counting from 0 at one end and from 1 at the other is jarring. When -1 points to the end of string rather than before the last char (cut str 0 (- (len str))) returns the first char instead of the empty string.
With -1 -> before last char:
(def chop ((o str "abcdef"))
(pr "Chop how many chars off the end of \"" str "\"? ")
(= n (coerce (cut (readline) 1) 'int)) ; bug in readline prepends #\newline
(prn "Chopped: \"" (if (is n 0) str (cut str 0 (- n))) "\"")) ; handle corner case
With -1 -> end of string:
(def chop ((o str "abcdef"))
(pr "Chop how many chars off the end of \"" str "\"? ")
(= n (coerce (cut (readline) 1) 'int)) ; bug in readline prepends #\newline
(prn "Chopped: \"" (cut str 0 (- -1 n)) "\"")) ; no corner case, but there's this -1 there
I probably made a stronger argument for -1 pointing to the end of string as it leads to shorter code.