So as the title explains, what's the difference between the implicit and explicit? Is implicit the function and explicit the operation? or is implicit the overture code and the explicit the VDM-SL specifications itself? I'm kind of confused
Implicit definition is where the function or operation is defined only by means of a (pre- and) post-condition, i.e. Boolean expressions. It does not say how the result in the post-condition is reached (though it implies it by giving the salient properties of the result). Such functions and operations cannot be routinely executed by the interpreter, but are perfectly valid in specifying the contract (assumptions and guarantees).
An explicit function or operation has a body that gives an imperative definition of how to compute the result, and therefore can be executed by the interpreter.
Related
Curried functions in F#. I get the bit where passing in a subset of parameters yields a function with presets. I just wondered if passing all of the parameters is any different. For example:
let addTwo x y = x + y
let incr a = addTwo 1
let added = addTwo 2 2
incr is a function taking one argument.
Is added an int or a function? I can imagine an implementation where "added" is evaluated lazily only on use (like Schroedinger's Cat on opening the box). Is there any guarantee of when the addition is performed?
added is not a function; it is just a value that is calculated and bound to the name on the spot. A function always needs at least one parameter; if there is nothing useful to pass, that would be the unit value ():
let added () = addTwo 2 2
F# is an eagerly evaluated language, so an expression like addTwo 2 2 will immediately be evaluated to a value of the int type.
Haskell, by contrast, is lazily evaluated. An expression like addTwo 2 2 will not be evaluated until the value is needed. The type of the expression would still be a single integer, though. Even so, such an expression is, despite its laziness, not regarded as a function; in Haskell, such an unevaluated expression is called a thunk. That basically just means 'an arbitrarily complex expression that's not yet evaluated'.
incr is a function taking one argument. Is added an int or a function?
added, in this case, is a named binding that evaluates to an int. It is not a function.
I can imagine an implementation where "added" is evaluated lazily only on use (like Schroedinger's Cat on opening the box). Is there any guarantee of when the addition is performed?
The addition will be performed immediately when the binding is generated. There is no laziness involved.
As explained by TeaDrivenDev, you can change added to be a bound function instead of a bound value by adding a parameter, which can be unit:
let added () = addTwo 2 2
In this case, it will be a function, so the addition wouldn't happen until you call it:
let result = added () // Call the function, bind output to result
No. But kind of yes. But really, no.
You can construct a pure functional language that only has functions and nothing else. Lambda calculus is a complete algebra, so the theory is there. In this model, added can be considered a parameter-less function (in contrast to e.g. random(), where there's one parameter of type unit).
But F# is different. Since it's a rather pragmatic mix of imperative and functional programming, the result is not a function[1]. Instead, it's a value, just like a local in C#. This is no implementation detail - it's actually part of the F# specification. This does have disadvantages - it means its possible to have an ambiguous definition, where a definition could be either a value or a function definition (14.6.1).
[1] - Though in a pure functional program, you can't tell the difference - it's the same as just doing a substitution of the function with a cached value, which is perfectly legal.
I have been creating specifications using implicit function definitions in VDM-SL and it has worked out very well. I now want to prototype the specification using explicit function definitions (no operations at this stage).
One way I can see of doing it is to create a new module that mimics the functions defined in the implicit specification, but give them explicit definitions.
I'm sure this could be done but I doubt it is ideal. There would be no link between the implicit and the explicit specification, though one is a refinement of the other.
Is there a recommended way of transitioning from implicit to explicit function definitions. Longer term I do want to investigate doing this formally, but in the first instance I simply want to implement the implicit function specifications to demonstrate the specification in action.
There is a formal process for the refinement of specifications, though it is quite laborious, especially since there isn't currently tool support for it.
If you preserve the implicit function type signatures and pre/postconditions, then the explicit versions are "certain" to be a refinement, assuming the implementation is correct for all inputs (which is where combinatorial testing can help). Note that you can also give an implementation (body) to a function written in an "implicit" style, which may simplify things:
f(x:nat) r:nat
== x + 1 -- This line added to the implicit spec!
pre x > 10
post r < 100
I'm playing with F# and the compiler warns me if I don't use some result (same problem described here). Since F# even has the function "Ignore" for that, it seems that it's somewhat important, but I don't really understand why - why doesn't C# care about it, but F# does?
One fundamental difference between C# and F# is that in F# everything is an expression (as opposed to a mix of expressions and statements). This includes things that in C-style languages are statements, like control flow constructs.
When programming in a functional way, you want to have small pieces of referentially transparent code that you can compose together. The fact that everything is an expression plays right into that.
On the other hand, when you do something that gives you a value, and you just leave it there, you are going against that mindset. You are either doing it for some side-effect or you simply have a piece of left-over code somewhere. In either case it's fair game to warn you that you're doing something atypical.
F# discourages, but doesn't disallow side-effects, and lets you have (potentially side-effecting) expressions executed in a sequence, as long as the intermediate ones are of type unit. And this is what ignore does - takes an argument and returns unit.
In F#, most everything is an expression with a value.
If you neglect the value of an expression in F# by either failing to bind it or return it, then it feels like you're making a mistake. Ignoring the value of an expression is an indication that you're depending on the side-effect of an operation and in F# you should be eschewing side-effects.
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 came across something in the Delphi language that I hadn't noticed before. Consider a simple record and a pointer to that record:
TRecord = record
value : double;
end;
PTRecord = ^TRecord;
Now declare a variable of type PTRecord:
var x : PTRecord;
and create some space:
x := new (PTRecord);
I noticed that I can access the value field using both the '.' notation and the '^.' notation. Thus the following two lines appear to be operationally equivalent, the compiler doesn't complain and runtime works fine:
x.value := 4.5;
x^.value := 2.3;
I would have thought that '^.' is the correct and only way to access value? My question is, is it ok to use the simpler dot notation or will I run into trouble if I don't use the pointer indirection '^.'? Perhaps this is well known behavior but it's the first time I've come across it.
It is perfectly sound and safe to omit the caret. Of course, logic demands the caret, but since the expression x.value doesn't have a meaningful intepretation in its own, the compiler will assume you actually mean x^.value. This feature is a part of the so-called 'extended syntax'. You can read about this at the documentation.
When Extended syntax is in effect (the default), you can omit the caret when referencing pointers.
Delphi has supported that syntax for close to two decades. When you use the . operator, the compiler will apply the ^ operator implicitly. Both styles are correct. There is no chance for your program doing the wrong thing since there is no case where presence or absence of the ^ will affect the interpretation of the subsequent . operator.
Although this behavior is controlled by the "extended syntax" option, nobody ever disables that option. You can safely rely on it being set in all contexts. It also controls availability of the implicit Result variable, and the way character pointers are compatible with array syntax.
This is called implicit pointer dereferencing for the structured types and inherited from the Delphi 1. This language extension aims to make accessing members of classes (classes are structured types and also instances are implicit pointers) by the means of membership operator (.) only, avoiding requirement for explicit dereference operator (^).
You can safely rely on the presence of this extension in the all Delphi compilers. For more flexibility you can test for the presence of this extension by using $IFOPT X+ conditional directive.