Arc Forumnew | comments | leaders | submit | rocketnia's commentslogin
1 point by rocketnia 4938 days ago | link | parent | on: Ask AF: Language+forum design?

"I get the impression LtU has the same effect going on, but with Haskell as the assumed common language."

I took a random selection of over ten LtU threads, and none of them had Haskell examples. Whoops. ^_^

A search for 10 Arc Forum "item" URIs turns up 7 which are part of a thread with sample Arc code and 3 which aren't. This isn't the same statistic, but it is telling. In this hypothetical forum+language design, the forum should be for discussing the language. Kinda insular. :-p

-----

1 point by akkartik 4938 days ago | link

Can you share the URIs you looked at?

-----

1 point by rocketnia 4937 days ago | link

I used http://www.random.org/.

For LtU, I did the selection a few days ago, and I didn't pay close attention.

For Arc Forum, I took exactly 10 random numbers from the range 1..16610:

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

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

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

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

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

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

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

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

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

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

-----

3 points by rocketnia 4939 days ago | link | parent | on: Some plans for code reuse

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

rocketnia: "I once wanted to design languages such that nobody would need to fork them, but I don't put much faith in that anymore, so I see it as a lower priority."

akkartik: "Welcome! :)"

rocketnia: "Er, welcome what? XD"

akkartik: "To the club :) It's a pretty select club, I think. Too much effort is expended to avoid forking in the name of 'reuse', IMO.

"But reuse in what context? Reuse all across the universe? I think the notion of reuse is often ill-posed. The only reuse that matters is in the context of a codebase. And as long as a codebase only has one fork of any software you can have unlimited forking in the world without reducing reuse.

"(This also kinda feeds into our conversations about namespaces and libraries and backwards compatibility.)"

---

Well, sorry to have to disappoint you. :)

Before, I valued reuse. Therefore, I tried to make it easy for a programmer to patch up any existing code for their purposes, no matter how buggy or out of place it was.

Now, I value reuse. Therefore, I'm trying to make it possible to build a foundation of absolutely impeccable libraries that don't need to be adapted. One library isn't everything to everyone; that's what making a new library is for.

These two approaches may be able to coexist, but the design of the first is contingent on the design of the second.

Ever since I started working on Blade and Penknife, I expected that even if my own products weren't impeccable, a community could take up that slack given the right tools.

---

"But reuse in what context? Reuse all across the universe? I think the notion of reuse is often ill-posed. The only reuse that matters is in the context of a codebase."

Reuse across all of society. We already reuse all kinds of technology. Or would you rather we spin our own cloth, etc.? http://arclanguage.org/item?id=16470

To be specific about my own goals...

Advanced research often finds its way into some specialized language that uses model checking or static typing to establish some necessary global assurances about the program. I specifically want to make a programming ecosystem that can harbor these meticulously concocted biomes. Convenience-centric styles will probably fit in the ecosystem too. Ideally, programs will start as hackish prototypes, then gradually harden into trusty, reusable foundations as the need arises.

---

"And as long as a codebase only has one fork of any software you can have unlimited forking in the world without reducing reuse."

I agree with this. I would like for each codebase to specify its dependencies as precisely as possible, even down to specific code revisions if necessary.

If necessary, it should fork the library and specifically use the fork instead of the original.

---

"This also kinda feeds into our conversations about namespaces and libraries and backwards compatibility."

I don't believe in perfect backwards compatibility, but I do believe it makes sense to update a utility while preserving its informal properties, as long as there's a clear indication of this informal development influence from the start.

One (rather comprehensive) informal influence on the code is its own author, so associating utilities with their author is an option I'm considering. (http://rocketnia.wordpress.com/2012/06/16/meaning-preserving...)

To get started though, I'm also considering the option of a single global namespace that guarantees no stability at all. :-p I like the idea of designing the language so that I can tack on different namespacing options as necessary.

-----

3 points by akkartik 4939 days ago | link

I think we're mostly in agreement. Perhaps we're just using different words.

"Would you rather we spin our own cloth, etc.?"

There's multiple ways to answer this:

a) There's a distinction between an end-user's view of the world and a developer/manufacturer's. From that perspective the analogy with spinning cloth might be misleading.

b) You're absolutely right that there always must be some set of abstractions we rely on, and that it can't be turtles all the way down. I'm not claiming everyone needs to fork every library they use. I'm claiming that even if they do so it shouldn't be cause for worry to anyone (besides themselves).

c) There is in fact lots of different ways to spin cloth. I don't think people in the cloth-spinning industry worry that somebody else in the world might use a different way to spin cloth. Think about all the competing kinds of wrenches, on metric vs imperial scales, etc. I think I might have found this disquieting and kinda ugly if I thought about it a few years ago. Now I have no problem with it. The tower of babel seems like a relatively minor issue to me now. If you're manufacturing a car or a crane you just decide what kind of wrench you're going to rely on and keep on cranking. Just avoid mixing multiple wrenches in the same assembly line.

For me there's no distinction between adapting an existing library and creating a new one. Perhaps the distinction is whether you try to move your patch upstream. You're trading some pain now for mitigating merging pains later. Depending on the context it might be worthwhile. However, it is valuable to think about this tradeoff rather than just flinch instinctively away from making changes to any libraries and try to patch them from the outside.

-----

2 points by rocketnia 4938 days ago | link

Well, it seems like I agree with all your possible answers. :) The interpretation I intended was b).

---

"For me there's no distinction between adapting an existing library and creating a new one. Perhaps the distinction is whether you try to move your patch upstream. You're trading some pain now for mitigating merging pains later. Depending on the context it might be worthwhile. However, it is valuable to think about this tradeoff rather than just flinch instinctively away from making changes to any libraries and try to patch them from the outside."

When you say it like that, it seems we're part of the same club after all. Glad to join you. ^^

-----

2 points by rocketnia 4939 days ago | link | parent | on: Ask AF: Language+forum design?

"I'm doing open-ended language design recently, without a single target language in mind. But I'd say I haven't considered any target language that would be up to this task!"

Actually, I'm a bit more hopeful than that now.

Hackability without breaking abstractions: One post can define a module, and another post can come along and define a different module in terms of the first one's implementation syntax. Maybe a module could do an import but then delete certain declarations by pattern-match and insert some new ones. Some declaration semantics could auto-erase earlier declarations, which is the same kind of feature that could be useful for REPL experimentation.

Fuzzy, living dependency resolution: Modules within a forum thread could refer to other modules in that thread by a simple tag system, which people could add and remove tags to after the fact. Underneath a unit test module, you could see a checklist of the implementations that satisfied it, and underneath any other module you could see a checklist of the unit tests it passed. Any post in the forum could refer to modules from other threads by using a slightly more cumbersome syntax, and this would be automatically cross-referenced at the original location.

Hmm, that's all I can think of for the moment.

-----

2 points by rocketnia 4939 days ago | link | parent | on: Ask AF: Language+forum design?

A recent LtU thread features some forum design wishlists: http://lambda-the-ultimate.org/node/4578

-----


"Firstly, that JavaScript amb link is very cool"

I'm glad to see there's a follow-up which uses continuation-passing style:

http://mihai.bazon.net/blog/amb-in-javascript/take-two

This seems more in the spirit of 'amb.

-----


"All of the classic examples of amb require some sort of global state to keep all of the continuation instances. But this is inelegant if you wanted to have multiple usages of (amb) which don't interfere with each other: suppose for example you want to create two threads - one for solving each Sudoku puzzle."

Woo! A kindred spirit! I scratched the same itch right when I was getting started with Arc:

https://github.com/rocketnia/lathe/blob/master/arc/amb.arc

I haven't ended up using this code, mainly because Arc isn't a great ecosystem for reentrant continuations. Arc's looping utilities use mutation, and one of the implementations of Arc which I like to support, Jarc, doesn't support reentrant continuations at all. Maybe you can give 'amb a better home.

---

"At the same time, you want (amb) to be a macro which lazily evaluates the possibilities"

Not me. My version of (make-amb) simply returns a procedure that chooses one of its arguments. Given that, we can get by with just one global macro for laziness:

  (lazy-amb my-amb (foo a b c) (bar d e f) (baz g h i))
  ==>
  ((my-amb (fn () (foo a b c)) (fn () (bar d e f)) (fn () (baz g h i))))
If you can stand to define a separate macro like 'lazy-amb and use it at each call site, it's a design pattern that obviates most use cases for fexprs.

-----

2 points by Pauan 4939 days ago | link

"If you can stand to define a separate macro like 'lazy-amb and use it at each call site, it's a design pattern that obviates most use cases for fexprs."

Indeed. You and I had discussed this quite some time ago, about having convenience macros that expand into thunks. This thunkification is clunky and awful, but it does indeed give many of the benefits of vau.

I still think any new Lisp should use vau, but thunkification is a great way to retrofit many of the benefits of vaus into older (?) Lisps like Arc.

-----


"I also just realized it might have some interesting uses as an alternative to exceptions. Rather than throwing an exception, you would instead return an object that has been tagged with an "exception" type."

This is monadic. Generally if you build a program out of a lot of functions of type (x -> MyWrap y) you can probably treat MyWrap as a monad, whereas if you build it out of a lot of functions of type (MyWrap x -> y) you can probably treat it as a comonad.

---

"By default this exception type would be propagated upwards until it reaches the top of the scope, but you can catch it by using pattern matching"

In this case you might be implementing it in a monadic way, but for most purposes the language user might as well treat it as a regular side effect.

I've been pondering the question of how to make the syntax of a language generic enough to integrate user-defined side effect models as though they're built in, just like this. However, this is a rabbit hole which has prevented me from getting very much done. :-p It's also straying pretty far from this thread's topic.

-----


"By the way... because they're (mostly) transparent and you can easily have multiple types attached to a single blob of data, you can use the type system to attach any arbitrary metadata you want. I can't help but feel that there's some connection there to monads..."

Yep! There's a pretty close connection to comonads, the opposite of monads. Comonads are for structures that can be unwrapped into a value at any time, but which can also be transformed without unwrapping by... confusingly, sending them a function that would unwrap them.

  extract :: MyWrap x -> x
  extend :: (MyWrap x -> y) -> MyWrap x -> MyWrap y
The point is that the wrapper that appears around y is generally related to the wrapper x started with. Note that extend's function argument might actually process multiple (MyWrap x) values, all hidden inside the main (MyWrap x).[1]

To illustrate, a pair of a Kernel expression and a Kernel environment can be used as a comonad, as long as we design Kernel expressions so that they can reify arbitrary values using 'quote. The extract method is eval, and the extend method bundles up the result as a literal expression together with the original environment.

[1] Aside from a few laws this has to follow, this kind of variation of behavior is particular to the implementation of each comonad. There will typically be some special-case utilities outside the comonad interface that take advantage of these specific features.

-----


"Well, I'm not rocketnia, but I think that's because"

You're a pretty good representative of... my past self. ^_^

---

"1) It uses symbols for types, at least in Arc 3.1"

Yep, there's no need to have first-class type tags of any sort when first-class wrapper and unwrapper functions could do that job.

---

"2) It plays poorly with ssyntax, since you can say foo?.x but you have to say (isa x foo)"

Nowadays I'd rather design the technical parts of the system first and then design the syntax to support it the best it can.

---

"3) If you want to add new types that behave like existing types, you need to always extend isa (or type), but with proper foo? functions you only need to extend those individual functions"

These days I would rather give library writers the ability to say what's extensible and what isn't. If it isn't extensible enough to support a new type, too bad. Fork the library.

This applies to languages too. If the language isn't extensible enough, fork it. I once wanted to design languages such that nobody would need to fork them, but I don't put much faith in that anymore, so I see it as a lower priority.

Anyway, I don't like Arc's 'type and 'rep because even though they can be used on any value, that misses the point. If I want to make a value that anyone can take apart, I'll use a table or a cons cell. Type wrappers are good for setting aside new areas of value space that _no_ existing utility knows how to handle yet.

--

"But I take it a step further in Nulan and also say that annotate/rep are poor because if you want to tag something with multiple types, you need to wrap it repeatedly: (annotate 'foo (annotate 'bar ...)) and then you need to unwrap it repeatedly: (rep (rep ...))"

In that particular case, I would consider making an 'unwrap-bar function and extending it to handle both 'foo and 'bar.

I would probably name 'unwrap-bar more descriptively, reducing its association with the concrete implementation details of the 'bar type, if only these weren't metasyntactic variables. :-p

Anyway, what I'm doing isn't necessarily strictly better than what you're doing. We're thinking of different overall systems.

-----

1 point by akkartik 4940 days ago | link

" I once wanted to design languages such that nobody would need to fork them, but I don't put much faith in that anymore, so I see it as a lower priority."

Welcome! :)

-----

1 point by rocketnia 4939 days ago | link

Er, welcome what? XD

-----

3 points by akkartik 4939 days ago | link

To the club :) It's a pretty select club, I think. Too much effort is expended to avoid forking in the name of 'reuse', IMO.

But reuse in what context? Reuse all across the universe? I think the notion of reuse is often ill-posed. The only reuse that matters is in the context of a codebase. And as long as a codebase only has one fork of any software you can have unlimited forking in the world without reducing reuse.

(This also kinda feeds into our conversations about namespaces and libraries and backwards compatibility.)

-----

2 points by Pauan 4939 days ago | link

"(This also kinda feeds into our conversations about namespaces and libraries and backwards compatibility.)"

Well, I only care about libraries because it means that (theoretically) one guy can write the code and a bunch of people can use it. The same is true of languages.

This is nice for things that are pretty stable, like regexps. Everybody knows regexps. The syntax is reasonably standardized across implementations. It doesn't make sense to have everybody write their own custom regexp implementation: just write one solid one and use it as a library.

But that only works when there really is a Single Right Way to do it. As soon as there's different goals and priorities, you just end up with a lot of little custom libraries (or lots of forks of libraries), in which case they might as well not be libraries to begin with, since they're only really useful to their original author.

This means you should only write libraries when there's some sort of standard or consensus. If there isn't, just write your code in a very flat simple style, no libraries needed.

---

As for namespaces... I don't actually care about those for code reuse. Libraries handle code reuse just fine with or without namespaces: look at Emacs Lisp as an example of a language with no namespaces and dynamic scope yet they seem to manage okay. C also has lots of libraries and code reuse yet doesn't have namespaces.

The reason I care about namespaces is that it makes certain things easier to reason about, that is, it reduces the cognitive load needed to design and understand a program. It also makes your programs shorter because when conflicts do arise, you don't need to do things like prefixing all your global variables, like they do in C/Emacs/Python/JavaScript/etc.

Well, that's the theory, anyways... in practice, I agree with you that traditional namespaces are overrated and only mildly helpful while requiring a lot of infrastructure to support them. An overall net loss that can only be recouped by writing many libraries over a long period of time that make use of the namespace system.

But I think Nulan is a bit unique in that it doesn't have traditional namespaces, but its immutable environments give you simple partitioning that I believe reduces cognitive load while not restricting you too much.

-----

1 point by rocketnia 4939 days ago | link

I've responded in a new thread, "Some plans for code reuse": http://arclanguage.org/item?id=16668

-----


While it seems fine to get rid of 'new, your reason for doing so doesn't make sense. Can't (%seq 1 2 3) be implemented as a procedure that calls (new seq? 1 2 3)?

-----

More