Arc Forumnew | comments | leaders | submit | absz's commentslogin
3 points by absz 6506 days ago | link | parent | on: Ruby-like in place list expansion

It's close, but doesn't quite have the same semantics: with your syntax, the variable has to be at the end, but using the @ for splicing, one can write (+ 1 2 @lst 3 4).

-----

2 points by bogomipz 6505 days ago | link

Yes, which also means the @ cannot reuse the lst object in this case, and therefore shouldn't do so when it happens to be at the end either. The dot is a notation for CONS, while @ would require copying the list that is spliced in.

Both . and @ are very useful and would be great to have available in any context.

-----

4 points by absz 6507 days ago | link | parent | on: Object Oriented Arc

I do think you leave out an important class (no pun intended) of problems for which OOP is helpful. Simulation, windowing systems... these are modeled elegantly by using classes and objects. In other words, OOP seems to me to be a good fit when the problem you are trying to solve deals with objects. The problem lies in trying to coerce other problems into noun-land.

-----

4 points by bayareaguy 6507 days ago | link

I think pg agrees with you in http://paulgraham.com/noop.html when he writes:

5. Object-oriented abstractions map neatly onto the domains of certain specific kinds of programs, like simulations and CAD systems.

Also for things like instance creation and method dispatch, OO languages can easily be both faster and more concise than functional languages. In a performance-sensitive setting like a desktop gui or a window system this can easily decide the issue.

But while simulation and OOP do have an important historic relationship, I don't believe you actually gain any special modeling expressiveness by making your objects adhere to a "class" framework. What's worse, the hardcoded assumptions OO languages make about classes and methods can confuse the assumptions in a simulation (e.g. because you can implement an "IS-A" relationship with inheritance doesn't mean you should).

If you want objects in a functional setting, you can just create the appropriate "factory" functions and have those functions return "objects" (i.e. functions with state in closures) which dispatch "methods" however you want them to, just like Jim Rankin did in the article at the top of the thread.

Personally I prefer the approach in SICP ( http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-19.html... ).

-----

2 points by absz 6507 days ago | link

I've skimmed the SICP link, and that does look like a good method. But I don't think they're mutually exclusive. As Jonathan Rees points out (http://paulgraham.com/reesoo.html), the definition of OOP varies; having just inheritance (coughjavacough) does make that problematic. Ruby's mixins and duck typing allow "is-a" without inheritance, thus alleviating some of the complaints.

I think that describing certain things, e.g. a windowing system, in terms of classes and objects does result in a useful description. "My window contains a button and a text field" maps nicely to an OO model. The implementation can (perhaps should) be user-level and/or functional with closures, but that modeling system can be powerful.

And of course, some of this is "taste;" I can't think very well in a visual paradigm, but I love a symbolic one. OOP may be orthogonal to your mental processes, in which case don't use it.

-----

2 points by jimbokun 6507 days ago | link

"Personally I prefer the approach in SICP ( http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-19.html.... )."

I was negligent in citing prior work. I had SICP in mind when I wrote my code.

The main differences are I wrapped it all up in a macro, I supported inheritance, and "method invocations" require one less set of parentheses:

    (define acc (make-account 100))
    ((acc 'withdraw) 50)
    50
    ((acc 'withdraw) 60)
    "Insufficient funds"
    ((acc 'deposit) 40)
    90
    ((acc 'withdraw) 60)
    30
I also didn't allow for initial arguments (yet). And you need to say "(vars 'varname)" to get values in method bodies instead of just "varname." I could probably fix both those things together.

But, generally speaking, the goal was to provide a macro for creating SICP style "objects."

-----

1 point by NickSmith 6507 days ago | link

Be interested to read your code Jim with your 'fixes'.

-----

4 points by absz 6508 days ago | link | parent | on: A solution for "unknown or expired link" ?

Well, I know that Gambit-C, which is a Scheme dialect, (http://dynamo.iro.umontreal.ca/~gambit/wiki/index.php/Main_P...) can; in fact, it can even serialize continuations.

-----

1 point by ryantmulligan 6506 days ago | link

I checked out Gambit-C but my question is, where is the community? It looks like it's just some guys research project, then some other researcher made Termite on top of it. It's community is either non-existent or in hiding, it would seem...

-----

1 point by absz 6505 days ago | link

That's a good question, and I have no idea--I just came across it because of Termite (which looks quite nice, by the way; those concurrency primitives [which are Erlang's, really] ought to be in Arc, but I digress). My point was really that it is technologically feasible to do so.

-----

1 point by ryantmulligan 6505 days ago | link

ah okay. You are saying it's possible to put this in Arc because it's in Gambit. Okay, sure. Gambit seems to be a much more performant implementation of scheme that Arc is striving to be. I think there is a lot to be said about serializing closures. Persistence is the nasty nasty dark secret of Computer Science. Our only tool that semi works is Relational Databases, but they aren't good for everything.

-----

1 point by absz 6508 days ago | link | parent | on: Multiple-variable [] literal implementation

Ah, I'd forgotten about that. I'll add it once I build git.

EDIT: Pushed. (It was easier, actually: there was already a total-macro-expander.)

-----

1 point by almkglor 6508 days ago | link

I've noticed you've added a 'filter function which duplicates the functionality of 'keep, except that 'filter does not (testify ...) the predicate function. It doesn't seem to be used by make-br-fn, so I'm wondering if you would like it retained.

-----

1 point by absz 6508 days ago | link

Oops. If that's not used by make-br-fn, then it's probably from an earlier draft. Off with its head!

-----

1 point by almkglor 6508 days ago | link

I've been looking at it, and it looks like it's added quite a few functions to the global namespace. Either we need to implement namespaces (or modules) quite well, or we need to make local functions easier to create.

-----

1 point by absz 6508 days ago | link

Hmm, that's a good point. I think that andmap and ormap are generically useful; the rest should probably be hiding. I could wrap all of make-br-fns in (with (free? (rfn free? ...))), etc., but then it would have to recreate the procedures each time... prefixing the procedures with * mbf- might be one way to deal with it, so they don't overload a common name. I don't know what the best option is (until we actually have modules, in which case it's clear)--thoughts?

-----

2 points by almkglor 6508 days ago | link

Well, the lisplike we use in the office doesn't have modules either, so our convention (actually just my, since no one else takes that language seriously) is to put a prefix name like yours.

Btw there might be a bug in 'arglist-vars - it uses (is arglist 'cons), maybe you meant (isa ...) ?

-----

1 point by kennytilton 6508 days ago | link

I use CL with its pretty nice package mechanism and I still prefix all my names with a mnemonic abbreviation of the package name. FWIW.

-----

2 points by almkglor 6508 days ago | link

LOL. In my off-time in the office I'm building a package system for that lisplike, basing off a macro that must enclose all forms that need to use packages; basically what it does is add the package name to the symbols that have been imported from the package.

-----

1 point by almkglor 6508 days ago | link

Also, for 'arglist-frees - from what I can hack, it tries to extract used variables in argument lists for optional arguments. So for example, your intent is that: (arglist-frees '(x (o y (some-var)))) => (some-var)

However, to extract the subexpression, you use car:cdar. I don't understand why.

-----

1 point by absz 6508 days ago | link

You are correct on both counts: that's two bugs. car:cdar should be cddr. I'm adding the * mbf- prefix, and I'll repush then.

-----

1 point by almkglor 6508 days ago | link

Will be waiting, since I intend to do the docstrings for them; unless you wish to do the docstrings yourself ^^

-----

2 points by absz 6509 days ago | link | parent | on: Poll: What would you change in Arc?

This would also allow things like a splice operator (mentioned here: http://arclanguage.org/item?id=540); if we had this (assuming that @x expands to (splice x)), you could write (let arglist '(4 5 6) (list 1 2 3 @arglist 7 8 9)) and get (1 2 3 4 5 6 7 8 9). This would actually be superior to apply in certain cases: (and x y @arglist) wouldn't have to evaluate y or the parts of arglist, whereas (apply and x y arglist) has the same effect in most cases, but does evaluate y, which can be problematic. I suppose one way to solve this would be to give values a "cer" (Current EnclosuRe) or some such; if lst were '(1 2 (a b) 3 4), then (cer x) = nil, (cer (car x)) = x, and (cer (car (list-ref 2))) = (list-ref 2). It's not clear what (cer (cdr x)) would be, but it would probably also be x.

-----

1 point by almkglor 6508 days ago | link

Personally I'd still implement this as a macro form, such that we would have a (spliceable ...) form which would scan its contents for splice-macros. So the syntax would look approximately like:

(spliceable (let arglist '(4 5 6) (list 1 2 3 (splice arglist) 7 8 9)))

(spliceable ...) would essentially be a generalization of the `() operator, except that ` will only scan for , while (spliceable ...) would scan for any splice-macros.

-----

2 points by absz 6510 days ago | link | parent | on: about (=)

Not quite. (car x) is treated specially as well, albeit slightly differently. If (car x) were evaluated, then the result would be more along the lines of (let temp (car x) (= temp 'z)), which would result in (car x) not actually changing. What happens is that = examines the first argument, and takes different action depending on whether or not it's a symbol (straight assignment) or not; if it's something else, it takes special action, like assigning the car in that case.

-----

4 points by pg 6509 days ago | link

What happens to the first argument is called inversion; = has to figure out where to put the value. And that could involve some evaluation, e.g. if you said

  (= (x y) 10)
Arc would have to evaluate y to figure out where in x to put the 10. So I should probably change the tutorial.

-----

2 points by quagmale 6509 days ago | link

Oh I see. Thank you for clarification.

It seems like (=) is a very special function. I'm not sure if I can even call it a function. Like, other functions can be passed as a value. But (=) doesn't seem like a function that can be passed around as a value.

-----

5 points by pg 6509 days ago | link

= is actually a macro; it works by transforming expression in which it occurs first.

-----