Arc Forumnew | comments | leaders | submit | ncommentslogin
271.

for all:

> sudo apt-get install screenie

> screenie

screenie is perfect.

Thanks for all!

272.

> In particular, this might very well break in bullet

It works:

    func foo (x): fn () x
    print ((foo 4)) // prints 4
I explained incorrectly: the interpreter env stack is basically a stack of bindings representing both "true" locals (i.e. locals on JVM) and environments representing lexical scopes. The latter are held for instance by functions, macros, modules explicitly, and also get implicitly created as required in e.g. looping primitives.

I'll reply to your other points tomorrow morning! (basically, I agree :))

273.

> My one reason for liking var is that you don't have to trek up to the top of a variable's scope to define it. If you do still have to trek outside a child varscope, that's not a full expression of the feature.

I'm afraid I don't understand what you mean by this. Maybe you could give a short example? As I see it, one way or another you need to mark out the "outer" scope, where you declare the lifetime of the variable (even though you don't know its value yet). Then somewhere in two or more branches of that scope the variable is set and used. IIUC you propose to write "varscope" at the top, and "var" further down. Doesn't that mean that whenever you define a variable, you need to write "varscope" before it? I somehow can't believe that, which makes me think I'm still not grokking!

> I assume you mean multiple vars of the same name in the same scope.

Yes, otherwise you quickly run in trouble with parent-scope scheme :)

> One consistent example of my rebellion is with loops, where I have no problem using "for ( var i = ..." for multiple loops in a single function.

The way that's handled in bullet is that when we encounter the for, we push a new environment, run the initialization, then push (and subsequently pop -- the interpreter holds a stack of environments representing runtime frames) an environment for each iteration of the loop. So it's ok to use the same variable name in subsequent for loops: the previous instance is not alive by the time current is reached.

> If func doesn't expand into var, I'd rather it did.

Here's the definition of "func" in bullet:

    macro func (name args :rest exprs)
      qquote
        set ,name
          fn ,args ,@exprs
So, yes, it's just a var binding. Note that this allows definition of "module" functions.

    func m.foo (): print "m.foo" 
    ==>
    set m.foo: fn (): print "m.foo"
By the way, even macros are defined as a macro:

    var macro
      tfm (name args :rest body)
        qquote: set ,name: tfm ,args ,@body
Macro's don't have any functionality analogous to Lambdas to capture variables from enclosing scopes.

As it should be clear by now, my implementation is a sort of illegitimate child of fexprs and macros. Basically, I've introduced all the weaknesses of fexprs in return for only some of the gains :)

In bullet, macros are values represented by the Transform class. Their definition is almost identical to Lambdas: they hold their formal parameters and their body as an AST. The only difference to Lambdas is how they're treated for evaluation purposes by the interpreter. Transforms (like Primitives which are basically fsubrs) receive their operands unevaluated. They are expanded at runtime, and the result of the expansion is then evaluated in the lexical environment of the call site. That means you can use macros in higher-order functions; they truly are first class.

Until now, this was an artifact of my interpreter design (emphasizing getting something up and running quickly). My intention had been to double back and fix the discrepancy with "real" lisps by doing the standard initial macroexpand traversal of the AST before evaluating. Either that or ditch the interpreter and write a compiler.

However, the material you've presented me with regarding fexprs is truly fascinating (no, I didn't know what they were before I read your post). I've just got to try these fexpr style macros; the idea of just controlling evaluation of operands, but otherwise being just like a regular function is very appealing.

In conclusion, I would appreciate if you could explain the varscope concept further. Again, what I don't get is whether need to write "varscope.." before you can bind a variable using "var..". I bang on about that because I'm loathe to introduce a feature that introduces such a high overhead for a single variable use. Or do you also have "lets" that work as in scheme?

Also, you kind of lose me in the last two paragraphs. It would be help if you could in some sense "sell" your concept it to me (please!): what extra bit of power is now available, that I can't express in my implementation? Maybe by the extra-cool use, I will understand the tradeoff in terms of extra typing for a variable declaration.

274.

When I first read your earlier question, I thought the question was about the names rather than how you specify the scoping. In any case, I opted for a binding declaration ("var") which consists of a single or series of bindings, rather than the "let" alternative where the bindings are over an explicitly specified body. To my mind, the former approach is simpler, and avoids extra nesting merely to define a new set of variables. It's the approach of e.g. arc and python. I don't see the gain of the varscope concept over just having "var" and "set" operate on the scope that surround the declarations and child scopes. Maybe I'm not understanding something? For example, in the situation that you describe, where you want to define a variable over a "large" scope, but don't actually know what to bind it to until later: what's wrong with just setting the variable to null until you know what its true value should be?

Here's how bullet handles things:

* A variable comes into existence either through a "var" or a "set" declaration. It is an error to have consecutive "var" calls in the same scope. Assignments are much more permissive: obviously you can use any number of them in any scope, and you don't need a "var" to preceed the first instance of a "set".

* If you write "var x ..." in a scope, and again in a child scope, then there is a new binding for x in the child scope that shadows the binding in the parent scope. On the other hand, "set x ..." not create a new binding if one already exists, so it will set x in the parent scope.

* All of this is handled by Environment class, using a rather pedestrian HashMap<Symbol, Variable>, where Variable is nothing more than a box. Obviously we capture variables that escape from functions when we analyze lambda definitions.

* The Environment functionality is reused to provide python-like modules. There is a special evaluation syntax (basically, it's the same syntax as for array/map access in clojure), which coexists quite nicely with the "." syntax:

    set y 5
    var x 42

    module m
      var x 1
      func dblx ()
        set x: + y: * x 2
      func printX ()
        print "x = " x

    print "x = " x
    print "m.dblx = ": m.dblx
    m.printX
    set m.x 50
    print "m.x = " m.x

    // prints:
    // x = 42
    // m.dblx = 7
    // x = 7
    // m.x = 50
An example of its use is in the bullet.bt, where I define a mini module for string functions:

    print: str.joinOn " " "modules" "are" "cool"
By the way, I toyed with removing "var" altogether, but I think I want to keep it; it'll come in handy when I build in an object system. Basically, within an object definition, variables will be member variables and you'll be able to refer to them within member functions ("mfunc" or "meth", not sure yet) either through "this.varname" or just "varname".

Also, in bullet "with" resembles pascal's "with" except that it returns the (effected upon) object:

    print: with (new ArrayList)
      add 1
      add "foo"
      ...
I'm not sure if I've answered your question. Thanks again for your input, it's awesome getting feedback on design decisions (there are so many decisions to make!).

EDIT: Added an example of "nested" set.

275.

> But why is 'for a primitive, when 'while can be the primitive and 'for can be a macro that expands to it?

For no better reason than I wrote the 'for primitive before I added macros!

I agree about labeled break and continue -- I specifically mention them in the article BTW. And to be honest, it has also occurred to me that this is just a local goto. So I have contemplating adding them.

The "point" approach is very cool. I like that it can translates into JVM features directly while remaining quite general (e.g. it's trivial to implement "return" using point). I think it's pretty easy to implement in the interpreter also, using exceptions (it's not going to win any speed contests), though you'd use labels and gotos when compiling.

Thanks for offering use of the code, I'm going to try it out. When I've got something worth reporting on I'll do so :)

276.

Having slept on this, I think I'm going to remove the (obj) ==> obj reduction. I think the gain is not enough to compensate the loss of transparency.

It's not even that big of a loss, since you can write:

    if (condition)
        true-clause   // 4-indent.
        false-clause
277.

Thanks for the tip about the formatting!

No, currently attempting to evaluate () is an error (and a bad crash with no error message, I'm embarrassed to say! [but now fixed and pushed]).

Your argument regarding () is pretty convincing. It's a bad idea. But I find the full-stop notation a bit jarring, not sure why. I'll try it and see if I get used to it... And I didn't want to tread on the "!" real-estate, given that's it's commonly used in identifiers.

I have to say I still lean slightly towards preferring a default of invocation for 0-arity functions, and using the "val" (again, id) function for passing the function itself.

Maybe the best approach is to offer a define-syntax functionality which somehow corrects the anomality (by visiting the AST and reducing without evaluating) before applying the macro transform. But that's quite possibly another can of worms...

278.
1 point by repos 5234 days ago | link | parent | on: Ask: Redirect news.arc to domain name?

The guys at HackerStreet India pointed me in the right direction, all you have to do is change the port number from 8080 to 80 here: https://github.com/rick2047/arc/blob/master/news.arc#L83

Or configure an nginx server that does it for you.

279.

Funny; we really are thinking about the same problems. bullet will currently puke if it encounters a lonely ')'. It's definitely sub-optimal. I think your solution of looking for words is the right way to go -- I didn't get around to implementing it though, because at some point I waded neck-deep into semantic analysis, code generation, ASM, invoke dynamic. Compilers really are fascinating creatures :)
280.

The pipeline in bullet is:

1. line processor: text lines are surrounded by brackets (textually!) where appropriated (i.e. 2-indents subject to nesting rules). Infix operators aren't touched. Result is stored in an array of CodeFragment, which is basically text + source code location.

2. reader: the forms are "read" and turned into B-expressions. You could call this the parsing stage, but lisp is a bit strange in some sense: there are two levels of parsing: the reader is the first, and the second is in the...

3. interpreter/compiler: every lisp has a starting phase which takes the "low-level" S-expressions comprising the code and parses it into the true semantic expression of the language: e.g. IfExpr, LambdaExpr, FnApplyExpr, etc.

Indeed, I think this is what makes lisp unique: all other languages have parsers which take you directly to step 3. The AST for semantic analysis purposes trees is basically just the parse tree. In lisp, you have to do work to get the AST -- but that's also why you get flexibility in macro writing.

I'd be happy to exchange implementation details. As I mention in the article, my code resides at

http://code.google.com/p/bullet-lang

My email is

martin at percossi dot com

feel free to email me if you have questions. It's nice to know other people are working on/thinking about the same problems! :)

281.

And just to be clear: in bullet, everything that's not a primitive or a function is an object :)
282.

Foo will get invoked because it's a function. In _bullet_ functions and primitives are invoked when "solo" on a line. Objects, on the other hand, aren't invoked.
283.

Hi, sorry for the late reply (it's now morning in Berlin :) , and thanks for the kind comments.

I opted for the "var" notation because I wanted to emphasize that the bindings are to _variables_; not to _values_ as is the case in (some) other lisps. I wanted to leave "let" for the case when you really want a constant. Another reason is purely aesthetic; the first programming language I learned was Pascal (ah, the fond memories :) which I always thought was a very _clean_ language. I wanted to evoke that (that's also why I use "begin" rather than "do" -- interestingly, once you use the 2/4-indent rules, you actually get pushed to _not_ using two-letter names, since 2/4-indent is ambiguous under 2-letter-name).

Regarding gradual typing, it would be nice because:

1. when programming in the large, knowing which types are expected and returned by a procedure is extremely helpful;

2. typing allows IDE autocompletion as well as refactoring (as you mention!);

3. allows for type hints for unboxed arithmetic, i.e. for performance.

1 & 2 are important, 3 much less so. My thinking is that if you're going for speed, you're probably going to want to do it in Java anyway. (Indeed, that I believe is one of the fallacies of Clojure: very few people are going to do performance-critical code in lisp. Having worked in e.g. a stat-arb fund, I can assert that no manager in their right mind would use anything other than tried-and-tested Java/C++/C# in that scenario.)

That's also why I eschew the idea of numerical tower in favour of Java's (inferior) numeric types. While the numerical tower is nicer, the standard statistical packages all use unboxed numbers -- what's the point of a beautiful tower edifice if you're going to chuck it out as soon as you do hard work?

284.

Yes, and it's not very difficult to get the behaviour:

    begin
         // 4-indent, so no parens: back in lisp world.
         (if (prefers-s-expresssions user)
           (print "bullet sucks")
           (print "why are you doing this to yourself??"))
285.

Well spotted; you've just waded into the dark corners of _bullet_ :)

The reason the 2-indent would evaluate (i.e. result in an invocation) is that '+', '-', etc. are _primitives_, which behave semantically like _functions_. For all other objects, the (1) rule applies.

Do you think this is too convoluted?

Alternatives I see:

1. The obvious is not to allow (obj-thing) ==> obj-thing. But then we'd need to define (func val (x) x) so that (e.g.):

     print: if (is-saviour name)
       val "go frodo"
       val "don't know you"
Otherwise, we'd have an error.

2. Make (fn-or-prim) ==> fn-or-prim (i.e. unifiy treatment of functions and objects, and in addition. To force evaluation of a 0-arity function, allow:

    save-middle-earth ()  // <-- () causes invocation.
What do you think?
286.

That quote was meant to be a bit flippant :)

You can break the line accross by using "begin" in _bullet_:

    cond
      name equals "Martin" ; begin
        print "what a"
        print "fool"
      name equals "Frodo" ; begin
        print "what a"
        print "saviour"
      name equals "Alex" ; begin
        print "err..."
        print "who knows?"
287.
2 points by kinleyd 5248 days ago | link | parent | on: Improving the Arc forum

If performance is not a factor, then I would suggest that all threads remain permanently open to commenting. That way an inactive thread could become active and show up under the 'comments' tab, and be of use long after the original contributors have left it.
288.
2 points by kinleyd 5249 days ago | link | parent | on: Improving the Arc forum

Off the cuff:

1) Grant admin access to arclanguage.org to a high karma ranking Arc Forum member to update that painfully outdated home page OR update the home page appropriately, with added links to other Arc focused sites such as https://sites.google.com/site/arclanguagewiki/

2) Regarding modifying the current HN based forum:

a. A built in search utility, of course

b. Add 'popular' and 'sticky' tabs to the existing new | threads | comments, etc tabs.

- The 'popular' tab could be a pure karma based collection of the heaviest threads (sum of plus votes, in descending order).

- The 'sticky' tab should be threads created or selected by the admin, usually a collection of how tos, work arounds and frequently sought help. Order should be admin settable, and there should be an area above each thread where the admin can clearly highlight the purpose of the thread.

- if possible, the sticky threads should remain commentable unlike normal threads that become uncommentable after a certain period. I'm not sure how this would affect the site from a performance standpoint as I understand HN currently uses this strategy to optimize performance.

289.
2 points by kinleyd 5249 days ago | link | parent | on: Improving the Arc forum

I agree that the HN format isn't ideal for the Arc Forum. However, to make even the littlest change here would require one of the active members here to have admin authority. Perhaps a good first start would be for someone here to talk pg or rtm into extending that privilege. We could then update some of the pages here that obviously need updating (eg. the install instructions page!) and begin the process of exploring how to modify HN to better suit a support forum.

I figure that everyone here will prefer to use a hack of the HN format, ie. must be Arc-based, rather than some other commonly used forum application. ;)

290.
1 point by kinleyd 5250 days ago | link | parent | on: (+ "string" 'symbol) is legal?

I agree. The Arc community will be better served with more forum focused ways to highlight important/useful threads no matter how old. Dedicated threads with high visibility, including sticky posts within those threads, are used to great effect at many successful community sites.

And search is a huge missing feature on this forum. Googling Arc Forum helps, but not the same thing.

291.
2 points by kinleyd 5250 days ago | link | parent | on: Hello Arc

Added an Installing Arc section to the wiki. It's very Ubuntu-centric right now and I will try to expand coverage in the future.

It doesn't yet show up on the top page of a Google search for "install Arc Lisp" but hopefully it will, and hopefully ahead of the Arc Forum | Install page. : )

292.
4 points by kinleyd 5252 days ago | link | parent | on: Hello Arc

@akkartik: I've been granted write privileges and have begun contributing to the wiki. I agree that some reorganization is necessary and have been taking a good look at the current state. I will focus on giving newbies some more hand holding at the getting started stages, and have opened a new Installing Arc page where I will be more elaborate in detailing installation instructions.

@pauan: I agree that Lite-Nu is the simplest in getting installed and started, and so will add Lite-Nu install instructions and references as well. Newbies should thus be attracted, deservedly, towards Lite-Nu especially in the initial stages. :) After that of course, it's up to them.

293.
1 point by kinleyd 5252 days ago | link | parent | on: Hello Arc

OK, duly noted. Thanks.
294.
1 point by kinleyd 5253 days ago | link | parent | on: Hello Arc

@Pauan, thanks. I like Lite-Nu. I particularly like the ability to run arc scripts from the command line and shell scripts written in Arc - very nifty! I think this gives one the opportunity to get deeply immersed in Arc.

I haven't played enough with it to provide other meaningful feedback or ask questions but I will as I starting using it.

295.
1 point by kinleyd 5253 days ago | link | parent | on: Hello Arc

Heh, thanks rocketnia. I did have a feeling it would incline toward client-side Arc in Javascript.

A static site generator in Arc also sounds interesting. I know that's the direction the Jekyll folks have taken, and doing something like Jekyll with Arc generated static code would be of interest to me. Let me tuck away this thought as I get up to speed with core Arc.

296.
2 points by kinleyd 5253 days ago | link | parent | on: Hello Arc

I will do that. It's been my habit to take lots of notes when trying out new stuff, so no worries about forgetting. :) I will distill it as well as I can and start making some contributions to the wiki. In the absence of an active admin here, hopefully the wiki will start showing up on top of Google Arc searches.
297.
1 point by kinleyd 5253 days ago | link | parent | on: Hello Arc

:) Thanks for the sympathy, and for the help. I am looking forward to some great times with Arc.

BTW, just looking ahead a bit, is it possible to run Arc on a shared hosting website? Not being mainstream, I don't see hosting services including Arc as an option, so I'd be keen to know if somehow it is technically feasible to set it up on a shared hosting website without having admin access to the box itself. I figure it would probably not be possible, in which case what would be the best options to develop on Arc for shared hosting situations?

298.
3 points by kinleyd 5253 days ago | link | parent | on: Hello Arc

Thanks Pauan and akkartik. I will definitely try out lite-nu and get back to you with my impressions. From the discussions on lite-nu here as well as the description on its Git page, it sounds very promising. I will also try out arc2js for the same reason.

@akkartik, I realize anarki is bleeding edge. I'm just grateful I stumbled across it and that it's working :) I will revert to the official Arc 3.1 version if it turns out to be too bleeding edge for me.

Now that I've been able to read more threads on this forum, I realize I would have saved a lot of time had I done so earlier. I wouldn't have gone on that long loop with Clojure and Common Lisp.

I think the main problem starts with the Arc Forum | install page (http://arclanguage.org/install). The instructions still are:

"1. Install version 372 of MzScheme. (Don't use the latest version. Versions after 372 made lists immutable.) 2. Get http://ycombinator.com/arc/arc3.tar and untar it.

3. Type mzscheme -m -f as.scm and you should get an Arc prompt.

4. If you ^C an Arc program, you'll get the Scheme REPL. Use (tl) to get back to the Arc REPL.

5. If you have questions or suggestions, post them on the forum. "

I assumed, naturally, that the most prominent page on the forum dedicated to installing Arc would be current. Hence the inevitable install run around.

If either of you are admins here, or if any admin comes across this comment, I would suggest that the Arc Forum | Install page REALLY needs to be updated. A lot of interest in Arc will be killed by frustrating experiences at set up time.

I did visit http://sites.google.com/site/arclanguagewiki (in fact I'd already bookmarked it). However, the instructions there just cover a series of links and could do well with a more detailed instruction set, especially if it is to appear more useful than the Arc Forum install instructions I've referred to above.

After I settle down with Arc, I will contribute in that direction.

299.

Yes, you're right, the prompt was being returned- I wasn't careful enough :)

It came as a surprise that HN serves directly off port 80- wonder how to they manage ssl from arc. I plan to serve via apache rewrite rules (reverse proxy)- and yes, sadly all ips in the arc logs show the local address. Thanks for this link. Also, who is that strange user on my logs (there are different names on different hosts)? :)

One OT question: Is there someway I can make comments on a story's page appear sorted by time- let's say- by pressing some button "show oldest/newest first" ? I have not yet started to hack the code- wanted to be a little comfortable with the system first. I assume working with news.arc would be enough for the news page?

300.

Hi, I posted a new reply (not nested in this one): http://arclanguage.org/item?id=15561
More