Previous Entry Share Next Entry
Release 1.3.12
querki
jducoeur wrote in querki_project
No bug fixes this time, just some small enhancements to QL that I've been wanting for a while.


Abstract Functions and Function Implementations: This one is only interesting to those who care about internals, at least for now.

I was recently reminded that the _plus function was a bit of a hack. It has a problem: it not only needs to work with several different numeric Types (Whole Number, Large Number, Floating Point), but it also works with Dates and Durations. So there was this weird little internal interface that indirected the actual implementation, in a way that was totally un-reusable. It's bothered me for quite a while, not least when I considered implementing _minus recently, and realized that I'd have to copy that hack.

So I've instead implemented something much cleaner, in Querki itself. There is now a concept of the Abstract Function -- a function signature that is generic (in the computer-science sense) over its received value or parameter. This Abstract Function doesn't do anything itself; instead, you can provide Function Implementations for various Types, saying how to do this Function for this Type. (This also works for Models -- the unit tests include defining a "Fraction" Model, and implementing _plus for that.)

None of this is exposed to the user level yet: building the right UI for all this is going to be quite a lot of work. But the concept is there under the hood, and it's fairly elegant: it's basically the camel's nose in the tent for some key functional-programming concepts, and will probably grow up to become the core of Typeclasses someday.


& and | operators: one of the things I've learned, slowly and painfully over the years, is that using _and and _or in expressions gets really, really annoying after a while. It's bulky, it's a lot to type, and it's hard to visually and mentally parse when you're reading your code. (Among other things, it contributes to the Lots of Stupid Parentheses effect.)

So I decided to blow in something I've been considering for a while, and which you intuitively *expect* the language to have: operators. This is, again, just the camel's nose in the tent. Operators are strictly hard-coded for the time being (and might stay that way), and simply translate to ordinary function calls. A & B is syntactic sugar for _and(A, B); A | B for _or(A, B). It's just a little thing, but I expect it to make it a bit easier to write readable expressions.

Important: for the moment, there is no associativity to these binary operators, and they can't be combined -- you can not stack them as A | B & C | D or anything like that. (We might add that later, but it makes the parsing much more complex, and requires us to deal with associativity, precedence order, and stuff like that.) And the clause on each side of the operator has to be a simple stage -- usually a Property or function call -- so you can't say Joe -> Present | Roger -> Present and have it do the right thing. (It means essentially Joe -> (Present | Roger) -> Present, which isn't what you want.) This would make these operators useless for any but the most trivial cases, which is why I put in one more enhancement...


Parentheses-delimited sub-expressions: you can now surround an Expression with parentheses to use it as a Stage. This means that you can combine operators as you would expect, but you *must* use parens around the clauses if they are non-trivial. So you can say something like (Joe -> Present) | (Roger -> Present) and it'll work as expected. I strongly recommend using parentheses for any non-trivial binary operations -- while they may eventually become unnecessary in some cases, they will always be correct.

This use of parentheses isn't limited to use with operators; you can substitute a parenthetical expression anywhere that a Stage is expected. So far, I haven't found a case where this is actually *useful* outside of Operators (in general, most places that you would want an Expression already takes one), but it wouldn't surprise me if other uses crop up.


This stuff is all new and experimental; please tell me if you find problems. Yes, I'm planning on introducing a '+' operator in due course -- indeed, I had planned to do it in this pass, but realized that I probably need to introduce a binary _add function for the semantics to work right. (The current unary _plus winds up with unintuitive semantics for an operator, and might eventually be deprecated.)
Tags:

?

Log in

No account? Create an account