What you want are the two typedefs intptr_t and uintptr_t . Each one is defined to be an integer big enough to hold a pointer (the former being signed, and the latter being unsigned); they aren't mandatory, though, so you might have
There we are, closures to the rescue :) Careful, though; remember that what you define with def will be accessible throughout the entire program. Use let or with for local functions. (I can't tell what you want there, but that's tripped people up on these fora before.)
The reason that w/uniq has the nil is so that + thinks it's adding lists, not numbers. Of course, pg could have just used join there, which would (a) eliminate the typing problem, and (b) in the nil case, produce (join), which is nil.
Also, if you want to reply directly to a person, click on the reply link below their post; it makes following the conversation a little bit smoother :)
Not quite. All that the comment is talking about is that Arc lists are different from Scheme lists. In Arc, they end with the symbol 'nil (e.g., '(1 2 3) is the same as '(1 2 3 . nil)); in Scheme, they end with '() (e.g., '(1 2 3) is the same as '(1 2 3 . ())).
apply is perfectly well-defined for n arguments: (apply f x xs) is the same as (apply f (cons x xs)). In other words, if we think about apply as providing the contents of a list as arguments to a function, this is only relevant to the last argument. The rest are passed to the function normally. This is a nicety, allowing us to write things like (apply map + list-of-lists).
I have never liked dynamic binding, and here (adapted from http://en.wikipedia.org/wiki/Scope_(programming)) is a classic problem with it. With both dynamic and lexical binding, the following code executes with the same result:
arc> (= x 0)
0
arc> (def f ()
x)
#<procedure: f>
arc> (def g ()
(let x 1
(f)))
#<procedure: g>
arc> x
0
arc> (f)
0
However, the result of g is different. With lexical binding, as we have things now
arc> (g)
0
With dynamic binding
arc> (g)
1
Closures no longer seem very closed, do they? This behaviour is entirely counter-intuitive. Or suppose that we have the following with lexical binding:
With dynamic binding, the last call ((mymap [f _] '(1 2 3 4 5))) would instead be an infinite loop: let F be [f _]. Then mymap's (f (car xs)) would be (F (car xs)). But the f referenced in F is actually F, as that's what f means in the local scope of mymap. So this is equivalent to ([F _] (car xs)), which is thus equivalent to ([[F _] _] (car xs)), which is equivalent to...
Dynamic binding is leaky, opens closures, and enables spooky action at a distance. That is why it is not the default binding.
The problem is the inherent difference between binding x in f where it is defined as opposed to binding x in f where it is called.
Dynamic binding fails in this condition:
(let x 42
(def set-x (new-x)
(= x (+ new-x 1)))
(def f ()
x))
The point is that x does not have a local or a global lifetime. Instead, it has a local or a global scope. The lifetime of every variable is like that of any object: when everything that can access it is lost, it gets garbage collected. That's even more consistent: not only are values automatically managed, locations are automatically managed too.
Global variables are always accessible and therefore will never be destroyed. But local variables might die as soon as the function exits, or it might live on. The only functions that have the right to access them, however, are those that are defined specifically to be within its scope. This means we have automatic protection.
Granted, you want to release this protection; presumably you have some plan to have programmers explicitly ask for the protection. I've programmed in a language which supports both dynamic and syntactic binding, and I always prefer using the syntactic binding. This is because while hacking into some other function's global is cool, some day you are going to do this accidentally, and when that day comes, you'll know why a library that used to work suddenly fails.
> This is because while hacking into some other function's global is cool, some day you are going to do this accidentally, and when that day comes, you'll know why a library that used to work suddenly fails.
Isn't that one of the goals of Arc? A hackable language?
That's a good reason if Arc is designed for
average programmers, but pg says it is explicitly
designed for good programmers.
This, it seems to me, is a very different use of "hack." It's more akin to forbidding (scar 'blue 'red), though not quite as severe: the latter is something nonsensical, and though you could hack together a meaning for it, it would certainly break down. The former case hacks around the definition of a function, but is also certain to break. These uses of "hack" are the ugly kind, closer to "kludge", not the beautiful or powerful kind.
LOL. This is where the semi-deliberate delicious ambiguity of "hack is kludge! what you mean? xy is x times y but 23 is not 2 times 3?" vs "hack is elegant! what you mean? e^(i*pi) = -1?" rears its ugly head.
Right. So tell me, suppose I have a very, very old piece of code, a classic, like this:
(def map1 (f xs)
" Return a sequence with function f applied to every element in sequence xs.
See also [[map]] [[each]] [[mappend]] [[andmap]] [[ormap]] "
(if (no xs)
nil
(cons (f (car xs)) (map1 f (cdr xs)))))
Now suppose in the future some random guy creates an application focused on cars. Since the guy knows he won't use 'car and 'cdr (car? cdr? pfft. that's so low-level! use proper let destructuring, foo!), he's quite willing to reuse the name 'car as a variable:
(let car (get-user-car)
(map1 color-wheel car!wheels))
Oops! map1's car function got overridden!
This is a rather contrived example, but hey, believe me: it'll happen, and it won't be as obvious as that. That's why dynamic variables are explicit in CL. That's why the default binding will be static.
The problem is that you then have a function whose return value depends on where it is called. Not when, but physically where. Also, imagine the havoc that would be reached with a memoized function: if f were memoized, then its return value would change depending on where it was called first. You could certainly argue that you shouldn't memoize f, but I think that you would find that this cropped up with functions that were actually a good idea to memoize.
The problem with being able to change f's return value by wrapping it in a lexical scope is that it destroys the "black box" abstraction of a function. You have to know how f is implemented to get a certain effect; alternatively, if you don't know how f is implemented, a simple change of variable name could wreak havoc with your program.
Actually, that name-change issue reveals another problem with dynamic binding: dynamic binding, I think, destroys alpha-equivalence (a fundamental property of the lambda calculus: http://en.wikipedia.org/wiki/Lambda_calculus#.CE.B1-conversi...). It might even play with the ability to do beta-reduction, but I'd have to think about that one more.
Gah, same gotcha as before. Mea culpa. I still stand by the first two paragraphs, though; it may not be alpha-equivalence, but changing names should rarely, if ever, affect distinct parts of the program.
apply is designed for calling a function with a variable argument list. Conceptually, you can write any function call of the form (f a b c) as (apply f (list a b c)). Its arguments are a function, any number of arguments, and a list at the end. For instance, suppose we have (apply f x y z (list a b c)). This is the same as writing (f x y z a b c).
In your example, you have (apply + '(a b) '((c d) (e f))); apply splices in the closing list, doing the same thing as (+ '(a b) '(c d) '(e f)); it should be clear why this returns '(a b c d e f).
That was not the clearest explanation in the world, so if you still have questions, please ask.
Also, a formatting tip: indent your code with two spaces and surround it by blank lines to have it formatted as code.
This must already sort-of exist: check out pg himself (http://arclanguage.org/user?id=pg). He's got 1190 karma, whereas almkglor, the current leader, has "only" 660. So somehow, pg's opting out of the "leaderboard" system, at least. If that's the case, it should be in news.arc somewhere (I'll look if I get the chance); of course, there could be some other reason I'm missing.
You'll also need mzscheme in your path; just download it from http://www.plt-scheme.org (v372 will work), and make sure you add the directory containing the binary to your PATH variable (`export PATH="$PATH:/path/to/the/directory/containing/the/mzscheme/binary"`).
I think that's everything, but I already had a highly customized setup. Feel free to ask any other further questions, but error messages/problems encountered would be helpful in those cases.