Arc Forumnew | comments | leaders | submit | eds's commentslogin
1 point by eds 6486 days ago | link | parent | on: Proposal: "." Syntax Sugar

Mind letting us in on how to get autocomplete to work with emacs and slime? (Or is there howto for it somewhere?)

-----

1 point by jmatt 6485 days ago | link

Sure.

Meta-TAB -> slime-complete-symbol

and

C-c M-i -> slime-fuzzy-complete-symbol

It can be found in the manual here:

http://common-lisp.net/project/slime/doc/html/Programming-He...

Also you can access documentation including the common lisp hyperspec:

http://common-lisp.net/project/slime/doc/html/Documentation....

It's an uphill battle to figure it out the first time but it gets easier.

-----

2 points by eds 6493 days ago | link | parent | on: Interpreter Manipulation?

That could be accomplished by redefining 'arc-eval rather than 'eval. 'arc-eval is used internally for evaluating top-level forms but not really anything else since it isn't exposed to arc, whereas 'eval could be used by arbitrary arc code. If you want to redefine the top-level evaluation function, than maybe what you want is some way to influence the results of 'arc-eval.

-----

1 point by almkglor 6493 days ago | link

So much easier:

  (def mytl ()
    (pr "arc> ")
    (eval (my-transformation (read)))
    (mytl))

-----

2 points by eds 6493 days ago | link

I guess I misunderstood your intention. I thought you wanted to be able to redefine the existing toplevel used by the arc interpreter itself, not define a completely new toplevel to be used in user code... (and yes, the latter is quite trivial).

-----

1 point by almkglor 6493 days ago | link

> I thought you wanted to be able to redefine the existing toplevel used by the arc interpreter itself

As opposed to emulating the existing toplevel in user code?

Allowing a redefinition of 'eval to work on the REPL will probably be OK, but still, there would be an impedance mismatch with functions that were defined before 'eval was redefined.

-----

2 points by eds 6496 days ago | link | parent | on: Interpreter Manipulation?

You mean 'eval? :)

-----

3 points by absz 6496 days ago | link

Not quite—from Bogart's post, it sounds like they want to be able to write (= eval my-magic-fn), and then (+ a b) would be passed through the new eval too. This would be interesting; I've been thinking about similar things.

-----

3 points by eds 6495 days ago | link

Ok, so you can't just redefine 'eval, you need to redefine 'eval and have MzScheme use that function on the Scheme side of things as well.

It looks like the 'arc-eval function is basically the one you want to redefine, since that is the one that is called inside the definition of 'tl2. In fact, the definition of 'eval is exactly the same as 'arc-eval except 'eval calls 'ac-denil on its arguments before compiling them. So basically what you would want to do would be to look up the value of the arc-side eval function and call that instead of hard coding a call to 'arc-eval. Right?

-----

6 points by absz 6495 days ago | link

It sounds like that should work: change the xdef of eval to

  (xdef 'eval (lambda (expr) (arc-prim-eval (ac-denil expr))))
, and then change arc-eval to

  (define (arc-prim-eval expr)
    (eval (ac expr '()) (interaction-environment)))
  
  (define (arc-eval expr) 
    ((eval '__eval) expr))
. The xdef should come soon enough to prevent something from calling a non-existent eval. Then, in Arc, you should be able to do

  (redef eval (expr)
    (prn " - debug - " expr)
    (old expr))
or whatever. Let me test that...

...

...yes, this works! Well, almost. I didn't really test it, but (a) ordinary things seem to get evaluated fine, and (b) the message is printed. It doesn't seem to hit everything in a macro-expansion, but I can't tell whether or not it should. For instance, I get (output reformatted for clarity)

  arc> (mac do+ (a b) `(do (prn ,a) (prn ,b) (+ ,a ,b)))
   - debug - (mac do+ (a b) `(do (prn ,a) (prn ,b) (+ ,a ,b)))
   - debug - (input-history-update
               (mac do+ (a b) `(do (prn ,a) (prn ,b) (+ ,a ,b))))
   - debug - (output-history-update
               (quote #(tagged mac #<procedure>)))
  #3(tagged mac #<procedure>)
  arc> (do+ 1 2)
   - debug - (do+ 1 2)
  1
  2
   - debug - (input-history-update (quote (do+ 1 2)))
   - debug - (output-history-update (quote 3))
  3
. (Of course, its output didn't have extra line breaks and had quasiquote instead of `, etc.) I feel like it should print

   - debug - (do (prn 1) (prn 2) (+ 1 2))
too.

<EDIT>

The problem is that ac-mac-call calls ac directly so that it can pass the current environment as a second argument. Perhaps arc-eval should take an optional environment argument too? But that would clutter things unnecessarily on the Arc side... anyway, the point is, after looking at it for all of five minutes, macros are tricky. (And I haven't even looked at ac-macex yet...) For instance, a simple test:

  arc> (nil 1 2)
  Error: "string-ref: index 0 out of range for empty string"
  arc> (redef eval (expr)
         (if (and (cons? expr) (~car expr))
           (cdr expr)
           (old expr)))
  #<procedure: eval>
  arc> (nil 1 2)
  (1 2)
  arc> (mac donil (a b) `(nil ,a ,b))
  #3(tagged mac #<procedure>)
  arc> (donil 1 2) ; Should return (1 2), but:
  Error: "string-ref: index 0 out of range for empty string"
</EDIT>

The downside is that, if it isn't slow now, it might well prohibit certain optimizations (though reading Steve Yegge's recent talk makes me think that I might well be wrong). Is this worth pushing on Anarki?

-----

2 points by eds 6505 days ago | link | parent | on: How to Setup an Arc News Forum - Step by Step

Good guide, I might want to try that some time.

Note that you don't technically need to install git since github can generate tarballs for you. (http://github.com/nex3/arc/tarball/master for the master branch, http://github.com/nex3/arc/tarball/stable for stable.) (Maybe this would be a good thing to put on kens's downloading Anarki guide.)

-----

4 points by eds 6507 days ago | link | parent | on: Learning Arc?

Personally, when learning Lisp, syntax wasn't a big issue. While the infix syntax of most languages is fairly intuitive, the rest of syntax (of e.g. C++ or Perl) is scary compared to Lisp's parens. (Although perhaps what puts people off is the frightening simplicity of Lisp's lack of syntax after using a conventional language.)

I started learning Lisp with Common Lisp, so I can make a couple of points there. pg's ANSI Common Lisp (http://paulgraham.com/acl.html) and Peter Seibel's Practical Common Lisp (http://gigamonkeys.com/book/) are both good texts, and go a long way toward getting you into Lisp. I also like Pascal Costanza's Highly Opinionated Guide to Lisp (http://p-cos.net/lisp/guide.html) and Steve Yegge's Lisp Wins (I think) (http://steve.yegge.googlepages.com/lisp-wins).

One the things that proved difficult about learning Lisp was choosing an implementation. There is no canonical implementation and as such I had to try several out before I learned which ones I enjoyed using. This survey of CL implementations (http://common-lisp.net/~dlw/LispSurvey.html) helped me when deciding which implementations to try. I recommend both CLISP (http://clisp.cons.org/) and SBCL (http://www.sbcl.org/), but that is just personal preference.

Also, the IDE was a difficult issue. I eventually settled on emacs with slime (http://common-lisp.net/project/slime/), although I have occasionally used Cusp, a Lisp plugin for Eclipse (http://bitfauna.com/projects/cusp/index.html). The main problem here was a lack of (thourough, easy to follow, up to date) instructions. Over the last couple of years I have gradually found good instructions on slime, but I can't seem to find any of them right now...

-----

2 points by absz 6507 days ago | link

I wasn't saying that the prefix syntax was an issue, just that it hampered popularity. Perception ≠ reality, after all. I too quite like the prefix syntax. I still slightly miss the simplicity of some of the Ruby code that I wrote, but the prefix syntax always wins me over; its benefits (macros) outweigh the minor downsides. Especially with []s and ssyntax.

And thanks for the CL thoughts! Regarding IDEs, I myself have ended up working just from the Mac OS X text editor TextMate (using Visor, which puts Terminal on a hotkey), and haven't found it problematic.

-----

3 points by eds 6508 days ago | link | parent | on: let redundant to with?

Yes, you can, but you might have to sacrifice the implicit 'do block in 'let. See http://arclanguage.org/item?id=3234.

That said, it might be good to remove the implicit 'do anyways, since as pg has said, an explicit 'do highlights non-functional code. Combining 'let and 'with would just be a convenient side effect.

P.S. If I am not mistaken I think this would also allow you to do destructuring as well...

-----

3 points by absz 6508 days ago | link

This is actually fairly simple to write (first defining butlast for convenience):

  (def butlast (seq)
    " Returns every element of `seq' but the last one.
      See also [[last]] [[cut]] "
    (cut seq 0 -1))
  
  (mac letn parms
    " Simultaneously ssigns the given (unparenthesized) local variables in the
      one-statement body.
      See also [[let]] [[with]] [[letns]]"
    `(with ,(butlast parms) ,(last parms)))
  
  (mac letns parms
    " Sequentially assigns the given (unparenthesized) local variables in the
      one-statement body.
      See also [[let]] [[with]] [[letn]]"
    `(withs ,(butlast parms) ,(last parms)))
Then letn is like with, but unparenthesized, and letns is like withs, but unparenthesized. (letn = "let n variables".) And yes, destructuring works.

-----

2 points by eds 6507 days ago | link

Perhaps these should be added to Anarki?

-----

1 point by absz 6507 days ago | link

Probably would make sense, but I'd rather wait until we had better names (I don't particularly like these.) Thoughts?

-----

2 points by almkglor 6506 days ago | link

'where ?

  (where foo (some-expression)
         bar (hmm that)
    (some-fn foo bar))

  (wheres val    (another-expression)
          grind  (grr val)
    (that-fn val grind))

-----

3 points by absz 6505 days ago | link

That's not bad... given?

  (given s1 (zebda oualalaradime)
         s2 (cake  symphony in c)
    (play s1 s2))
  
  (givens arc (language-by             pg)
          mzs (implementation-language arc)
    (run-in arc mzs))

-----

3 points by skenney26 6505 days ago | link

Okay, for some reason I can't get this out of my head.

What if "let" becomes "as", given becomes "let", and givens becomes "lets"?

-----

1 point by absz 6505 days ago | link

I would be reluctant to change let, since it's a standard operation in arcN.tar. Otherwise, there's probably some merit to that.

-----

3 points by eds 6505 days ago | link

And now we're back to waiting for pg to do something ;)

-----

1 point by almkglor 6505 days ago | link

Heck no. We can do this ourselves. Remember, the textual transformation to transform let's is just that: a textual translation. It should be possible to create an automated translation tool (based off raymyers' treeparse) that will handle this for us.

Let the old version of 'let be Arc2Let, and the proposed new let be Arc2.7Let. Let the old version of 'with and 'withs be Arc2With and Arc2Withs, respectively. We need to determine if each Arc2Let in the source is composed of a single expression in the body. If it is, we leave it as-is. If it isn't, we simply replace it with Arc2.7As.

For each Arc2With we determine if the body is composed of a single expression. If it is, we replace it with Arc2.7Let, removing the parens around the Arc2With bindings. If it isn't, we leave it as-is. Ditto for Arc2Withs, replacing it with Arc2.7Lets.

We define an expression simply as a sequence of whitespace, base-expression, and whitespace. We define whitespace as being either a comment (either #||# or ;) or ordinary whitespace.

A base-expression is simply a symbol, a number, a character, a string, a quote-expression, a comma and comma-at expression, or a list. A quote-expression is simply the ' quote or ` backquote character followed by maybe whitespace, followed by an expression; comma and comma-at are defined similarly. A list is composed of an opening parenthesis followed by many expressions, followed by a closing parens.

We can determine if a 'let form has several expressions by defining two variants of a 'let form. An Arc2Let is composed of ( <maybe whitespace> let <whitespace> <expression> <expression> <expression> [many <expression>]), and that we have to transform to Arc2.7As (by filtering out the let expression using treeparse 'filt). An Arc2.7LetCompatible is composed of just (let <expression> <expression> <expression>), which we do not transform.

----

Of course, this does represent a veritable fork of the Arc code ^^.

-----

1 point by absz 6505 days ago | link

I would leave with and withs alone, so that we have the option of the implicit do (also because it makes it easier to implement given/Anarki-let :P). And why not use a code-tree-walker if we want to do this—isn't that the point of Lisp?

Still, I don't quite think the fork is worth it….

-----

2 points by almkglor 6505 days ago | link

Actually the point of messing with the existing 'with / 'withs is to force the programmer to consider using the new form of 'let. ^^

The problem of using a code-tree walker is: you lose the comments, which are arguably about 50% the value of the code.

-----

1 point by absz 6504 days ago | link

Right, comments. Just a little important, aren't they? :P

You raise a good point... it's the same number of parentheses either way. But in that case, why not just have let and lets (as given(s)), and be done with it?

-----

3 points by almkglor 6504 days ago | link

> let and lets (as given(s))

Done and on the git ^^

Edit: as an aside, given that pg has said that he'll modify Arc as if there's nobody else programming in it, and that he does not appear to be using Anarki, eventually when Arc3 does come around, it is very possible that Anarki will be incompatible with Arc3. We may very well need to build a converter program in the future to transform Arc2-base Anarki to Arc3-base Anarki, so my abstract nonsense may very well be necessary in the future.

-----

1 point by absz 6504 days ago | link

Thanks!

And general abstract nonsense is almost always a good thing... still, that is worrisome.

-----

1 point by almkglor 6505 days ago | link

'given looks good - I think it's better than 'where.

-----

1 point by almkglor 6507 days ago | link

'these?

  (these x y
         r v
    (foo x r))
Of course it turns into 'theses ....

-----

2 points by skenney26 6506 days ago | link

Interesting idea. I like "as".

-----

2 points by almkglor 6506 days ago | link

  (as var x
      foo 42
    (something var foo))
Hmm...

But how about withs ?? == ass? ^^

-----

1 point by skenney26 6506 days ago | link

Think of it as short for assign :)

-----

1 point by skenney26 6505 days ago | link

How about "as" and "az"?

-----

5 points by absz 6497 days ago | link

I've been programming with given(s) for a little while now, and I really like it. Can't say why I'm so vehement, but it's definitely a Good Thing™. Thank you for bringing this up again (and a "thank you" to aidenn0, if he/she is still reading these fora, for suggesting this in the first place).

-----

3 points by almkglor 6497 days ago | link

An interesting bit about 'givens is that it makes functional programming in an imperative style almost seamless:

  (givens f (car n)
          v f!v
          _ (prn v) ; v isn't being set properly in some cases for some reason...
          l (combinatorics f v)
          _ (prn l) ; debugprint
    (is l 'undef))

-----

2 points by bOR_ 6497 days ago | link

I'm not on anarki, but I've followed this discussion. If you use given rather than let and with, which of the two options below would come out?

arc> (= b "abba") "abba" arc> (let (a b) (list 1 2) (pr a b)) 121 arc> b "abba" arc> (with (a b) (list 1 2) (pr a b)) abbaabba"abba" arc>

-----

2 points by absz 6497 days ago | link

  arc> (given (a b) (list 1 2)
         (pr a b))
  121
The difference between given and let/with is that you cannot have more than one statement in the body of the given. For instance:

  arc> (given (a b) (list 1 2)
         (prn "Here")
         (pr a b))
  Error: "Can't understand fn arg list \"Here\""
What's happening here is that given is trying to bind (prn "Here") to (pr a b), but (naturally) can't bind a string; it takes the first n args, where n is the largest even number less than or equal to the number of arguments provided, and interprets them as variables. You must, therefore, write

  arc> (given (a b) (list 1 2)
         (do
           (prn "Here")
           (pr a b))
  Here
  121
.

Also, I highly recommend switching to Anarki. It's got bugfixes and enhancements galore (and even runs on the newest version of mzscheme).

-----

4 points by bOR_ 6496 days ago | link

So the main drawback of given is that you need to make your do explicit? mmm, I never liked it implicitly anyway ;).

-----

3 points by absz 6496 days ago | link

It's the only "drawback", if such it is. I feel that since you need extra parentheses for either the body or the variables, it's better to wrap the body in a do, since that's less common.

-----

4 points by eds 6508 days ago | link | parent | on: Why Arc is bad for exploratory programming

http://arclanguage.org/item?id=5259

-----

2 points by eds 6509 days ago | link | parent | on: Dual syntax for Arc

> However, the implementation was very slow, so I think it is not used by many of us those days.

I'd like to find a way to improve the speed of the current infix implementation, but I'm not sure it can be done without using macros, which would require some sort of type inferencing or static type declarations.

-----

1 point by almkglor 6508 days ago | link

Or just:

  (nfx a + b - c)
An old dorky buggy implementation for CL:

http://www.dwheeler.com/readable/readable/trunk/gloria-infix...

-----

1 point by sacado 6509 days ago | link

Once again, maybe the solution is ssyntax (yep, this is my new motto :) :

  { a + b + c } <==> (+ a (+ b c))
Hmm, not an easy one though.

-----

1 point by absz 6509 days ago | link

The ssyntax system cannot do this: it's limited to working on symbols. You would need access to the readtables in mzscheme to make this work.

-----

3 points by eds 6511 days ago | link | parent | on: Multiple Return Values?

The one nice thing about multiple values that I don't think returning lists accomplishes is that if you have a function that doesn't expect to receive multiple values, it will just use the first value returned. For example, in CL, #'truncate returns two values, the quotient and the remainder. But if you pass the return values of #'truncate to #'+, it just pretends you only passed a single value.

  * (truncate 5 3)
  1
  2
  * (+ (truncate 5 3) 6)
  7
I don't know of any way to make this work implicitly with returning lists... you would need to explicitly test if you were receiving a list and then destructure it accordingly. (Please correct me if you know of a better way around this.)

-----

5 points by almkglor 6511 days ago | link

Using (car:truncate ...) is th best I could think of ^^

-----

2 points by bOR_ 6509 days ago | link

that's pretty close to perfect.

Anyway, I suppose that the programmer knows what the output is of a certain function, and not be surprised if a function churns out a list rather than two values ;).

-----

3 points by bogomipz 6506 days ago | link

What if your function originally just returned one value, but at some later point you realize that a second value would be useful in some situations?

With multiple return values you can just extend it without breaking existing clients. If, on the other hand, you add a list wrapper around the returned values, all call sites must be changed to take car of the list.

-----

3 points by bOR_ 6500 days ago | link

That would be useful indeed. The flip side of the coin might be something that was sort of mentioned in 'on lisp'. If all functions return only one value (be it a list or a single value) by default, you can write a general memoize layer around functions that doesn't have to check how many multiple return values are returned.

I also noticed a carif function in arc. If you are worried about single values that will become lists in the future, you might start using carif in your current clients.

-----

3 points by eds 6513 days ago | link | parent | on: Programming in a vacuum

"When you're writing desktop software, there's a strong bias toward writing applications in the same language as the operating system. But with Web-based software, especially when you have the source code of both the language and the operating system, you can use whatever language you want."

http://www.paulgraham.com/avg.html

-----

6 points by almkglor 6513 days ago | link

We still need libraries, right?

String processing libraries especially, also database libraries, distributed message passing libraries, etc.

Everyone! Come! Let us go forth and write more Arc libraries, document them real good, and push them on Anarki!

-----

4 points by kens 6512 days ago | link

Writing libraries is a Good Thing, but trying to create a large collection of libraries for Arc strikes me as a bit of a hopeless cause. After all, Lisp hasn't been able to reach a "critical mass" of libraries and it has many, many more people involved.

I think Arc would be much better off with a way to leverage existing libraries. Easiest would be to use MzScheme's libraries, but that set of libraries is somewhat limited. (I'm currently experimenting with using MzScheme's OpenGL library from Arc; the object-oriented stuff is a big pain since it doesn't play well with Arc.)

Alternatively, if Arc had a way to access the libraries from, say, Python, .Net, or Java, it would gain access to a huge library base. A couple big problems are how to map the language datatypes between the languages, and how to get the runtimes working together.

-----

3 points by almkglor 6511 days ago | link

Maybe make an arc2jvm? Perhaps even arc2java, I'm sure a subset of Java can be made sufficiently C-like to compile down to (and we even get GC for free).

> A couple big problems are how to map the language datatypes between the languages

Bingo

-----

1 point by etal 6509 days ago | link

Looks like this is the official way to put another language on top of Java:

https://scripting.dev.java.net/

(Note their subtle language that any higher-level language running on the JVM is a "scripting" language.)

I haven't worked with it, but if it handles the mapping of Javascript's type system onto the JVM, then maybe it will do the same for Arc.

-----

1 point by almkglor 6508 days ago | link

Does it allow "script" code to be compiled down to java or jvm bytecode, or is it strictly an interpreter for the scripting language?

-----

1 point by etal 6508 days ago | link

I'm miles out of my league here, but in the interest of science I grabbed the spec, JSR-223. Here's the juice:

Introduction:

  The original goal of JSR-223 was to define a standard, portable way to
  allow programs written in scripting languages to generate web content. In
  order to do this, it is necessary to have a common set of programming
  interfaces that can be used to execute scripts in scripting engines and
  bind application objects into the namespaces of the scripts. Therefore, in
  addition to a framework for web scripting, the specification includes a
  standardized Scripting API similar to the Bean Scripting Framework. It uses
  the Scripting API to define the elements of the Web Scripting Framework.

  [...]

  There are several areas which are intentionally omitted from the
  specification:

  - The specification does not define how scripting languages should enable
    the use of Java objects in scripts, although it is assumed that the
    scripting languages implementing the specification have this
    functionality.

  - The specification does not distinguish between scripting implementations
    that compile script sources to Java bytecode and those that do not.
    Script engines that do can be used to implement the specification, but it
    is not required.

  - The specification makes no requirements of scripting languages or the
    syntax uses to invoke the methods of Java objects in the languages.

Overview:

  In this specification, a scripting engine is a software component that
  executes programs written in some scripting language. The execution is
  generally performed by an interpreter. Conceptually an interpreter consists
  of two parts: a front-end which parses the source code and produces an
  internal representation of the program known as intermediate code, and a
  back-end which uses the intermediate code to execute the program.

  The back-end of the interpreter, also known as the executor, uses symbol
  tables to store the values of variables in the scripts.

  [...]

  Scripting engines which implement the fundamental scripting interface
  defined in this specification are known as Java Script l20 Engines.
  Conceptually, a Java Script Engine can be thought of as an interpreter, but
  this may not actually be the case. For instance scripts executed by a
  single Java Script Engine may be executed internally by different
  interpreters.

Technologies:

  - Java Language Bindings – Mechanisms that allow scripts to load Java
    classes, create instances of them and call methods of the resulting
    objects.

  - General Scripting API – Interfaces and classes that allow script engines
    to be used as components in Java applications.

  The specification does not deal with issues of scripting language design or
  interpreter implementation.

So, it looks like the way you interpret, compile and execute the code is your own business, but if your own ScriptEngine implementation matches the specified API, it will work with existing Java tools and frameworks, particularly for the web. It's modeled after Rhino, so some parts of the Rhino back-end might be directly reusable.

-----

3 points by absz 6512 days ago | link

This is a good point. There is a C interface, and C has innumerable libraries, but working with C can be… icky.

-----

4 points by stefano 6513 days ago | link

What about a TODO list of needed libraries? Everyone could peek one and develop it. I'm currently working on a client side http library.

-----

3 points by almkglor 6511 days ago | link

TODO:

  A reasonably quick substring-matching library
  Database

-----

2 points by absz 6513 days ago | link

Hear hear! Let there be libraries! The school year's almost over, and I'll contribute more then. And I second the idea of a list of necessary libraries that stefano proposed.

Also, has anyone else found themselves accumulating a file of utility functions? I have one with a little fewer than 30 functions which I find generally useful. There's probably some duplication of standard stuff, but there are also things that aren't. If other people have these, we might put the common functions on Anarki.

-----

2 points by almkglor 6513 days ago | link

I suggest that such simple routines be pushed onto Anarki then.

As an aside: it would probably be a good idea to start adding docstrings to everything in Anarki; this would help catch duplication of effort.

-----

3 points by stefano 6512 days ago | link

What about automatically collecting every function/documentation pair and putting everything on the Anarki wiki?

-----

1 point by almkglor 6511 days ago | link

Err, I don't understand exactly what you mean, can you expand on this?

-----

1 point by stefano 6510 days ago | link

I mean scanning Arc files or, better, the help* table and gather information in text files formatted in a wiki-friendly format in order to easily put them on the Anarki wiki.

Edit: have a look at the file lib/help-to-wiki in Anarki (just pushed it).

-----

1 point by almkglor 6509 days ago | link

Arki doesn't support tables yet.

Also, Arki supports <arc></arc> tags, which adds the help* table entries as the mouse hover strings on symbols.

-----

More