a few days back i was trying the new ORM for delphi from Devart called EntityDAC, well i was reading the docs specific the LINQ part, when i saw something like:
Linq.From(Emp).Where(Emp['Sal'] > 1000)
got to say that wake me up the first moment i saw. the expression "Emp['Sal'] > 1000" isn't a lambda expression?! since the trial version is this component don't come with sources i couldn't figure out how Where function/procedure is declared.
reference: http://www.devart.com/entitydac/docs/ -> Linq Queries -> Linq Syntax -> Scroll down to Where session
I mentioned this in a blog post a few months ago. I don't have the source to look at, but it's almost certainly done this way:
The expression Emp['Sal'] returns a value of a record type
This record has operator overloads declared on it
The Delphi language defines operator overloads as functions, and does not require them to return any specified or intuitive type. Therefore, the > operator here does not return a boolean, but rather another record.
By chaining these operators, an expression tree can be created, which can be evaluated by their LINQ evaluator.
Related
I'm wondering if Cypher (Neo4j query language) has a Backus-Naur Form.
If so, where can I find it? If it doesn't, could you guess one?
There isn't a separate grammar that's published for the language, but you can get what you need from this.
Internally, neo4j uses a package called Parboiled to do its parsing of cypher. In the cypher compiler software package, generally in /src/main/scala/org/neo4j/cypher/internal/compiler/v2_3/parser/ you'll find a file called Clauses.scala which essentially implements the cypher grammar in Scala.
To take a really simple example, here's the definition of the LIMIT clause:
private def Limit: Rule1[ast.Limit] = rule("LIMIT") {
group(keyword("LIMIT") ~~ (UnsignedIntegerLiteral | Parameter)) ~~>> (ast.Limit(_))
}
Simple enough, a LIMIT clause is the keyword LIMIT followed by an unsigned integer literal or parameter.
Note that one of the more complicated bits of the syntax is in Patterns.scala where you see what constitutes a graph pattern. Other resources like that are included by reference in Clauses.scala.
I don't have a lot of experience with parboiled, it's quite possible that given this definition of the grammer, parboiled could generate a grammar in whatever syntax you might like.
Is it legal for a record to have a nullable field such as:
type MyRec = { startDate : System.Nullable<DateTime>; }
This example does build in my project, but is this good practice if it is legal, and what problems if any does this introduce?
It is legal, but F# encourage using option types instead:
type MyRec = { startDate : option<DateTime>; }
By using option you can easily pattern match against options and other operations to transform option values as for example map values (by using Option.map), and abstractions such as the Maybe monad (by using Option.bind), whereas with nullable you can't since only value types can be made nullables.
You will notice most F# functions (such as List.choose) work with options instead of nullables. Some language features like optional parameters are interpreted as the F# option type.
However in some cases, when you need to interact with C# you may want to use Nullable.
When usign Linq to query a DB you may consider using the Linq.Nullable Module and the Nullable operators
F# does not allow types that are declared in F# to be null. However, if you're using types that are not defined in F#, you are still allowed to use null. This is why your code is still legal. This is needed for inter-operability, because you may need to pass null to a .NET library or accept it as a result.
But I would say it is not a good practice unless your need is specifically of inter-operability. As others pointed out, you can use the option feature. However, this doesn't create an optional record field whose value you don't need to specify when creating it. To create a value of the record type, you still need to provide the value of the optional field.
Also, you can mark a type with the AllowNullLiteral attribute, and F# compiler would allow null as a value for that specific type, even if it is a type declared in F#. But AllowNullLiteral can't be applied to record types.
Oh and I almost forgot to mention: option types are NOT compatible with nullable types. Something that I kind of naively expected to just work (stupid me!). See this nice SO discussion for details.
function A: Boolean;
function B: Boolean;
I (accidently) wrote this:
A or B;
Instead of that:
if not A then
B;
The compiler rejects the first form, I am curious why?
With short circuit evaluation they would both do the same thing, would they not?
Clarification: I was wondering why the language was not designed to allow my expression as a statement.
The first is an expression. Expressions are evaluated. Expressions have no visible side effects (like read or write a variable). Both operands of the expression are functions and those can have side effects, but in order to have side effects, a statement must be executed.
The second is a statement. It compares the result of an expression and based on the evaluation calls another function.
The confusing part, is that in this case, Delphi allows us to disregard the result of a function and execute it as a function. So you expect the same for A or B. But that is not allowed. Which is great because the behaviour is ambiguous. For example, if yo have lazy evaluation enabled. And A evaluates to true, is B called yes or no.
Simply, because the compiler is expecting a statement and the expression that you have provided is not a statement.
Consult the documentation and you will find a list of valid statements. Your expression cannot be found in that list.
You asked in the (now deleted) comments why the language designers elected not to make such an expression count as a statement. But that question implies purpose where there may have been none. It's perfectly plausible that the designers did not decide not to do this. Rather they never considering doing it in the first place. Languages are generally designed to solve specific problems. It's perfectly plausible that the designers simply never considered treating such expressions as statements.
The first form is an expression which evaluates to a Boolean value, not a statement.
At its heart, Delphi is Pascal. The Pascal language was designed by Nicklaus Wirth and published in 1968. My copy of the User Manual and Report is from 1978. It was designed with two purposes in mind, as a teaching language and as one that was easy to implement on any given machine. In this he was spectacularly successful.
Wirth was intimately familiar with other languages of the time (including Fortran, Cobol and particularly Algol) and made a series of careful choices with particular purposes in mind. In particular, he carefully separated the concept of 'actions' from 'values'. The 'actions' in Pascal are the statements in the language, including procedure call. The 'values' include function calls. In this and some other respects the language is quite similar to Algol.
The syntax for declaring and using actions and values are carefully kept quite separate. The language and the libraries provided with it do not in general have 'side effects' as such. Procedures do things and expressions calculate values. For example, 'read' is a procedure, not a function, because it retrieves a value and advances through the file, but 'eof' is a function.
The mass market version of Pascal was created by Borland in the mid 1980s and successively became Turbo Pascal for Windows and then Delphi. The language has changed a lot and not all of it is as pure as Wirth designed it. This is one feature that has survived.
Incidentally, Pascal did not have short-circuit evaluation. It had heap memory and sets, but no objects. They came later.
I have a problem understanding co-existence of "null" and Option in F#. In a book I have read that null value is not a proper value in F# because this way F# eliminates the excessive null checking. But it still allows null-initialized references in F#. In other words, you can have null values but you don't have the weapons to defend yourself with. Why not completely replace nulls with Options. Is it because of compatibility issues with .NET libraries or languages that it's still there? If yes can you give an example that shows why it can't be replaced by Option?
F# avoids the use of null when possible, but it lives in the .NET eco-system, so it cannot avoid it completely. In a perfect world, there would be no null values, but you just sometimes need them.
For example, you may need to call .NET method with null as an argument and you may need to check whether a result of .NET method call was null.
The way F# deals with this is:
Null is used when working with types that come from .NET (When you have a value or argument of type declared in .NET, you can use null as a value of that type; you can test if it equals null)
Option is needed when working with F# types, because values of types declared in F# cannot be null (And compiler prohibits using null as a value of these types).
In F# programming, you'll probably use option when working with .NET types as well (if you have control over how their values are created). You'll just never create null value and then use option to have a guarantee that you'll always handle missing values correctly.
This is really the only option. If you wanted to view all types as options implicitly when accessing .NET API, pretty much every method would look like:
option<Control> GetNextChild(option<Form> form, option<Control> current);
...programming with API like this would be quite painful.
I am having a brain freeze on f#'s option types. I have 3 books and read all I can but I am not getting them.
Does someone have a clear and concise explanation and maybe a real world example?
TIA
Gary
Brian's answer has been rated as the best explanation of option types, so you should probably read it :-). I'll try to write a more concise explanation using a simple F# example...
Let's say you have a database of products and you want a function that searches the database and returns product with a specified name. What should the function do when there is no such product? When using null, the code could look like this:
Product p = GetProduct(name);
if (p != null)
Console.WriteLine(p.Description);
A problem with this approach is that you are not forced to perform the check, so you can easily write code that will throw an unexpected exception when product is not found:
Product p = GetProduct(name);
Console.WriteLine(p.Description);
When using option type, you're making the possibility of missing value explicit. Types defined in F# cannot have a null value and when you want to write a function that may or may not return value, you cannot return Product - instead you need to return option<Product>, so the above code would look like this (I added type annotations, so that you can see types):
let (p:option<Product>) = GetProduct(name)
match p with
| Some prod -> Console.WriteLine(prod.Description)
| None -> () // No product found
You cannot directly access the Description property, because the reuslt of the search is not Product. To get the actual Product value, you need to use pattern matching, which forces you to handle the case when a value is missing.
Summary. To summarize, the purpose of option type is to make the aspect of "missing value" explicit in the type and to force you to check whether a value is available each time you work with values that may possibly be missing.
See,
http://msdn.microsoft.com/en-us/library/dd233245.aspx
The intuition behind the option type is that it "implements" a null-value. But in contrast to null, you have to explicitly require that a value can be null, whereas in most other languages, references can be null by default. There is a similarity to SQLs NULL/NOT NULL if you are familiar with those.
Why is this clever? It is clever because the language can assume that no output of any expression can ever be null. Hence, it can eliminate all null-pointer checks from the code, yielding a lot of extra speed. Furthermore, it unties the programmer from having to check for the null-case all the same, should he or she want to produce safe code.
For the few cases where a program does require a null value, the option type exist. As an example, consider a function which asks for a key inside an .ini file. The key returned is an integer, but the .ini file might not contain the key. In this case, it does make sense to return 'null' if the key is not to be found. None of the integer values are useful - the user might have entered exactly this integer value in the file. Hence, we need to 'lift' the domain of integers and give it a new value representing "no information", i.e., the null. So we wrap the 'int' to an 'int option'. Now, if there is no integer value we will get 'None' and if there is an integer value, we will get 'Some(N)' where N is the integer value in question.
There are two beautiful consequences of the choice. One, we can use the general pattern match features of F# to discriminate the values in e.g., a case expression. Two, the framework of algebraic datatypes used to define the option type is exposed to the programmer. That is, if there were no option type in F# we could have created it ourselves!