you'll see that items is a table, as declared by "(with (items (table)...", used to store items loaded from file. The definition of an item is found closer to the top in the "(deftem item" block
3) The bang operater a!b is equivalent to (a 'b) and is used as a shorthand for table lookup.
3) The bang operater a!b is equivalent to (a 'b) and is used as a shorthand for table lookup.
But there are many instances it has been used on single symbols like !id. How do I interpret that?
EDIT: I found out! !id is only used with compare, so this is applied to the body like (items!story items!poll). But my problem still exits, how do I find out the story is a local post or a one with url.
But my problem still exits, how do I find out the story is a local post or a one with url.
You mean whether it's a topic with a URL and no text or a topic with text and no URL, right? Hmm, it looks like 'item-page is responsible for displaying the /item?id=... URL, and that calls 'display-item-text to display the textual content of the post. The implementation of 'display-item-text looks like this:
(def display-item-text (s user)
(when (and (cansee user s)
(in s!type 'story 'poll)
(blank s!url)
(~blank s!text))
(spacerow 2)
(row "" s!text)))
So it seems stories have both URLs and text internally, but the text is never displayed unless (blank s!url). That's probably the test you're looking for.
I agree, Code for Code was pretty much what I was looking for as well. I think I like lisp mainly because I can actually work on metaprogramming topics easily and without straying too far from the code itself. Arc doubly so, since the language definition is so short.
Oh, and I don't have anything scheduled for Feb. 31 either ;)
But your point of course is that the compiler shouldn't impose an ordering. It's a convention for structuring codebases.
Whenever I see something like a design pattern, I immediately start wondering what kinds of "complete abstraction" could be built out of it, to either make its construction easier, or less likely to be broken by someone new joining the project. As useful for testability as this revelation seems, it also seems like it could be easily broken by someone merely not observing the order conventions.
So, is there any way to get the advantages of testability associated with sequential definition that doesn't require prior knowledge of the pattern, or would it be better if the compiler forced ordering in the first place? What are the advantages in terms of succinctness or expressiveness given by out of order programming?
For myself I'm still finding out the patterns and abstractions for writing code in order.
For example, the rule says that code shouldn't depend on code that comes after it, but then what about recursive definitions? Asking the question leads me to discover things like extend and defrule.
And there are subtler questions that I don't really understand yet. For example, if I write unit tests that work with earlier definitions, then those unit tests should still work after the later definitions are loaded. So later definitions should extend the program while letting the earlier definitions still work. But what does that mean exactly?
the rule says that code shouldn't depend on code that comes after it, but then what about recursive definitions? Asking the question leads me to discover things like extend and defrule.
It's really interesting that you start with a simple axiom and end up with something largely overlapping with the principle of separation of concerns.
I say 'overlapping' because I sense you aren't quite using extend in the same way. You're using extend more rigidly (no negative connotation intended) than me, chopping your functions up into finer bits than I do.
Hmm, I find myself focusing on the parallel between overrideable definitions in dynamic languages like arc and ruby, and languages like haskell that permit defining functions in multiple clauses:
Yes, I should probably clarify that usually I'm not that rigid either. Most of my Arc programming is exploratory programming (figuring out what it is that I actually want) not engineering (implementing a solution to known goals).
Now the transition from exploratory programming to engineering is an interesting one. If I've created a program (using primarily exploratory programming techniques) and then I want my program to run on Arc-m, that's then largely an engineering effort with an easy to describe goal: I want my program to work the same on Arc-m as it does on Arc-n.
Paying the cost of "always" doing things in a particular rigid way doesn't make sense during exploratory programming. But if then I have a particular engineering task (convert this to run on Arc-m), turn introducing some rigidity (scaffolding if you will) is often useful: writing some unit tests, getting the dependencies laid out clearly.
The benefit of interleaved tests is future-proofing, like you said. When making large, non-localized changes such as the move to a new arc, you know exactly the first test that failed. But what happens when you scale from one file to two? When multiple files of definitions depend on arc.ss?
The benefit of keeping tests in a distinct file: you can reason about the final semantics of definitions without thinking about the order in which they are orchestrated. That is a useful simplification except when making large localized changes.
I'm not certain of these ideas by any means. Just thinking out aloud. Would it be useful to analyze the tree of dependencies, and to execute tests in dependency order regardless of the order they're written in? Would that give us the best of both worlds?
it also seems like it could be easily broken by someone merely not observing the order conventions
If you like unit tests, one option to make sure that you've put things in dependency order is instead of running your unit tests after loading all the code, put the unit tests for a definition immediately after the definition. That way those unit tests for the definition will run before the rest of the code has been loaded.
You end up having to fight the compiler in some situations just to get code to compile. But that isn't an argument about succinctness or expressiveness, so now I'm starting to rethink it.
Update: After reading the recent thread on hygiene (http://arclanguage.org/item?id=12700) I'm reminded that one of the themes of arc was to assume you're building for smart programmers, and to avoid constraints as far as possible. Hygiene is a constraint. Ordering definitions is a constraint. Better to replace them with conventions.
Ah, but that still doesn't address the question of why ordering is so much better and whether or not some of those reasons can be reified into useful code. Yes, many things can be typed in repetitively by intelligent people who can remember design patterns. But that doesn't prevent those same intelligent people from wanting utilities and macros to simplify the process.
So far none of the macros and higher-order functions that constitute complete abstractions require you to code that way, they just allow you to if you wish. And help you by making the computer do a lot of the heavy lifting.
It's possible that this abstraction is just that - too abstract - but if so I'd still like to know why.
Hmm, are there any kinds of constraints that help you write less code?
I'm finding this to be a useful line of inquiry; it's also starting to get too abstract. Are you still thinking about sequential definition, or about design patterns in general?
Why ordering is better: sequential definition helps localize errors. So where does this answer lead?
Yes, the main purpose of Anarki is as a place for people to share the work they've done on/for arc. Since arc itself is easily modified, a lot of the code on Anarki actually changes the language. There is also a fair amount of library developed there as well, though since most important library functions can be lifted from Racket that's not so much of an issue.
However, beyond simple bug fixes pg hasn't ever discussed much about changing the language itself with the community. As far as I know, none of even the truly good, simplifying and useful features of Anarki are planned to be lifted to arc.
That's not always true. If a programming system supported first class macros, then an anonymous macro could be passed in as an argument to a function, which could then apply it in a more sophisticated way at run time. I.e. apply it to a list of objects that don't even exist at compile time.
However, since arc does not support first-class macros, and neither do most compiled languages that I'm aware of, you're basically correct.
I definitely think that shunting stderr to stdout, or any other method of displaying errors would make a huge difference.
I agree with you and am working on it. The only reason I've hesitated with that feature is that certain errors reveal information about the sandboxing mechanism I'm not sure I want people to have.
arc> (system "ls")
subprocess: `execute' access denied for /bin/sh
Maybe it's not really an issue at all, but it is something I've worried about. I could probably hedge my bets by displaying more generic error messages than the ones the sandbox provides.
Other than that, it's really rather cool. Great job!