Programming language: DrRacket/scheme
Hey guys,
I am preparing for my first comp sci midterm, and have two quick questions that I'd love to get some input on:
(1) What exactly is the difference between a data definition and a
structure definition?
I know that for a data definition, I can have something like:
;; a student is a
;; - (make-student ln id height gradyear), where
;; - ln is last name, and
;; - id is ID number, and
;; - height is height in inches, and
;; -gradyear is graduation year
but what is a structure definition?
(2) What exactly are the alphas and betas in contracts that come before functions, i.e.
take : num α-list -> α-list
Thank you in advance!
Quote from How to Design Programs (HtDP):
A DATA DEFINITION states, in a mixture of English and Scheme, how we
intend to use a class of structures and how we construct elements of
this class of data.
Given a problem to solve you as a programmer must decide how your input data is represented as values. In order for others to understand your program it is important to document how this is done in detail.
Some input data are simple and can be represented by a single number (e.g. temperature, pressure, etc).
Other types of data can be represented as fixed number of numbers/strings. (e.g. a cd can be represented as an author name (string), a title (string) and a price (number)). To pack a fixed number of values as one value one can represent this a structure.
If one needs to represent an unknown number of something, say cds, then one must use a list.
The data definition is simply your description of how the data are represented in your program.
To explain what a structure definition is, I'll quote from HtDP:
A STRUCTURE DEFINITION is, as the term says, a new form of definition.
Here >is DrScheme's definition of posn:
(define-struct posn (x y))
Let us look at the cd example again. Since there are no builtin "cd values" in Racket, one must define what a cd value is. This is done with a structure definition:
(define-struct cd (author title price))
After the definition is made one can use make-cd to construct cd values.
In order to explain that autor and title are expected to be strings, and price is expected to be a number, you must write down a data definition that explains how make-cd is supposed to be used.
I forgot to answer your second question:
(2) What exactly are the alphas and betas in contracts that come
before functions, i.e.
take : num α-list -> α-list
The alpha is supposed to be replaced with a type.
If take get a integer-list (list of integers as input) then the output is an integer-list.
If take get a string-list (list of strings as input) then the output is an string-list.
In short if take gets a list of values with some type (alpha) as input, then the output is a list of values with the same type (alsp alpha).
Jens Axel Soegaard's answer is correct, but does not elaborate on the relationship between the two, which I would state as follows.
A DATA DEFINITION describes to the reader how a value is going to be represented using Racket values.
Sometimes, the "built-in" values aren't enough, and we need to define a new kind of data, like the "CD" that Jens refers to. In order to define a new kind of data, we often use a STRUCTURE DEFINITION.
Put differently: some data definitions require structure definitions. Some do not.
If I were to elaborate any more, I would just be badly recapitulating HtDP; if what I've said thus far does not make sense, go read HtDP. :)
Related
I've recently started to experiment with alloy for a project, and I have run into an issue unequal arities. Here is a simplified example. I have four signatures:
Word
Definition
Document: a document has a text (a sequence of words)
Dictionary: a dictionary maps a sequence of words to a sequence of definitions (to keep it simple, let's say that a word should have exactly one definition)
Here is a minimal code example:
module dictionaries
open util/relation as relation
sig Word {}
sig Definition {}
sig Document {
text: seq Word
}
sig Dictionary {
entries: seq Word,
defseq: seq Definition,
define: Word->Definition,
}{
//dictionary maps word to def only for the word present in dictionary
dom[define] = elems [entries] function [define, elems [entries]]
//content of the list of defintions
defseq = entries.define
}
//assert all word in a dictionary have a definition
assert all_word_defined {
all w: Word | all dict: Dictionary | some def: Definition |
//w in dict.entries implies w->def in dict.define
}
check all_word_defined
So my questions are:
How do I constrain dictionaries so that each word in the dictionary maps to exactly one definition? Is it correct to do it as in the code above?
How do I check that this constraint is respected with an assertion? Obviously the bit of code w in dict.entries implies w->def in dict.define does not work, because w in dict.entriesand w->def in dict.define do not have the same arity, and I get the error message "in can be used only between 2 expressions of the same arity"...
I think you're struggling with seq and assertions more than arity.
seq is not very common in Alloy, you only use it when you need to change the ordering of elements. In this example, I do not see any need for ordering in the current description.
Assertions verify invariants of the whole model. What you try to assert is more a fact that you state in the model than what you assert. Assertions are useful if you have defined operations and want to verify that certain things can never happen regardless of how those operations are executed and in what order. I.e. the assertions verify the consequences of the model, not the facts. (Although sometimes it is useful to verify something in other words.)
Alloy is incredibly powerful in navigating through global tables. Despite looking object oriented, the trick is to understand that fields are actually global tables that are joined. (This is what took me a long time to get.)
You should not have redundant information in the model. You entries, defseq and define can be modelled with functions on the define table.
The base language is very powerful. For a problem of this size you often do not need any utilities. Especially relation seems quite redundant after you feel the relational model of Alloy.
Ok, step by step:
A Documents is a sequence of words:
I would just make a Document a set of Word because that more natural and a lot easier to use. In this problem, the ordering of words does not play a role so using normal sets is ok it seems? (Counting the words would require a seq.)
sig Word {}
sig Document {
text: Word
}
A dictionary maps a sequence of words to a sequence of definitions (to keep it simple, let's say that a word should have exactly one definition)
I think you mean that a Dictionary can map a word to one definition? Does EVERY word have an entry? Or are there some words that have an entry? You say 'a' which I take as some words having one Definition? If so:
sig Definition {}
sig Dictionary {
define : Word -> one Definition,
}
The define table (which is Dictionary->Word->Definition) has a constrain that for a given Dictionary->Word combination, there must be one Definition. This means not all Words have to be in the table, but if a Word is in the table then there must be exactly one Definition. (you can model this also with other constraints. Best is to write out a table and look at the columns.)
You define entries as the set of Word in the Dictionary. You can model this better as a function:
fun Dictionary.entries : set Word {
this.define.univ
}
The first join selects the this Dictionary in the define table and removes the first column. The second join removes the last column.
And similar for defseq:
fun Dictionary.defseq : set Definition {
this.define[univ]
}
The box join [] just joins the inside of the square brackets with the first column of the table before it, leaving the Definition column. That is:
(univ).(this.define)
How do I check that this constraint is respected with an assertion
I think it is not clear what you try to assert. (Which is the power of a formal language that you discover this!) In Alloy you state as a fact that a Word in a Dictionary maps to one Definition. There is no use asserting something you have defined as a fact. Before you can assert you first need more definitions.
Normally you start writing a predicate and then look for examples of your model. For example, if we want to see one of the infinite Dictionary's then we could write:
pred show( d : Dictionary ) {
d.define.univ = Word
}
run show for 5
In this example, you will see a Dictionary where every word has a Definition.
I've written a blog that might be useful for you: http://aqute.biz/2017/07/15/Alloy.html
Good morning,
I want to understand how can I describe something using the first order logic.
For example I want to describe what is a film (an entity) and what is an attribute (for example actor: Clooney) for the film. How can I describe that using the first order logic?
******* UPDATE ********
What I need to explain in first logic order is:
ENTITY: an element, an abstraction or an object that can be described with a set of properties or attributes. So I think that I must says that the entity has got a set of attributes with their respective values. An Entity describes an element, an abstraction or an object.
ATTRIBUTE: an attribute has always got a value and it always associated to an entity. It describes a specific feature/property of the entity.
DOCUMENT: a pure text description (pure text it not contains any html tags). Every document describes only ONE entity through its attribute.
To state that an object has a certain property you would use a single place predicate. For example, to state that x is a film you could write Film(x). If you want to attribute some value to an object you can use two (or more) place predicate. Using your example you could say that Clooney starred in a film as Starred(clooney, x).
There are certain conventions that people use. For example, predicates start with capital letters (Actor, Film, FatherOf) and constants start with a lower case letter (x, clooney, batman). Constants denote objects and predicates say something about the objects. In case of predicates with more than one argument the first argument is usually the subject about which you are making the statement. That way you can naturally read the logical formula as a sentence in normal language. For example, FatherOf(x, y) would read as "x is the father of y".
Answer for the update:
I am not sure whether you can do that in first order logic. You could describe an Entity as something that has certain properties by formula such as
\forall x (Entity(x) ==> Object(x) | Element(x) | Abstraction(x))
This is a bit more difficult for the Attribute. In first order logic an attribute ascribes some quality to an object or relates it to another object. You could probably use a three place predicate as in:
\forall attribute (\exists object (\exists value (Has(object, attribute, value))))
As to the document, that would be just a conjunction of such statements. For example, the description of George Clooney could be the following:
Entity(clooney) & Has(clooney, starred, gravity) & Has(clooney, bornIn, lexington) & ...
The typical way to do this is to explain that a specific object exists and this object has certain attributes. For example:
(∃x)(property1(x) & property2(x) & ~property3(x))
aka: There exists a thing that satisfies properties 1 and 2 but does not satisfy property 3.
Your current question formulation makes it unclear as to what you mean by attributes and documents. Perhaps towards your idea of attributes: it's possible to describe as the domain of property1 all the entities that satisfy it; so, for example, the domain of blue is all blue objects.
First-order logic has nothing to do with HTML -- are you trying to use HTML to represent an entity in first-order logic somehow? It remains incredibly unclear what your question is.
What is the difference between values and list or cons in Racket or Scheme? When is it better to use one over the other? For example, what would be the disadvantage if quotient/remainder returns (cons _ _) rather than (values _ _)?
Back in 2002 George Caswell asked that question in comp.lang.scheme.
The ensuing thread is long, but has many insights. The discussion
reveals that opinions are divided.
https://groups.google.com/d/msg/comp.lang.scheme/ruhDvI9utVc/786ztruIUNYJ
My answer back then:
> What are the motivations behind Scheme's multiple return values feature?
> Is it meant to reflect the difference in intent, or is there a
> runtime-practical reason?
I imagine the reason being this.
Let's say that need f is called by g. g needs several values from f.
Without multiple value return, f packs the values in a list (or vector),
which is passed to g. g then immediately unpacks the list.
With multple values, the values are just pushed on the stack. Thus no
packing and unpacking is done.
Whether this should be called an optimization hack or not, is up to you.
--
Jens Axel Søgaard
We don't need no side-effecting We don't need no allocation
We don't need no flow control We don't need no special-nodes
No global variables for execution No dark bit-flipping for debugging
Hey! did you leave the args alone? Hey! did you leave those bits alone?
(Chorus) -- "Another Glitch in the Call", a la Pink Floyd
They are semantically the same in Scheme and Racket. In both you need to know how the return looks like to use it.
values is connected to call-with-values and special forms like let-values are just syntax sugar with this procedure call. The user needs to know the form of the result to use call-with-values to make use of the result. A return is often done on a stack and a call is also on a stack. The only reason to favor values in Scheme would be that there are no overhead between the producer return and the consumer call.
With cons (or list) the user needs to know how the data structure of the return looks like. As with values you can use apply instead of call-with-values to do the same thing. As a replacement for let-values (and more) it's easy to make a destructuring-bind macro.
In Common Lisp it's quite different. You can use values always if you have more information to give and the user can still use it as a normal procedure if she only wants to use the first value. Thus for CL you wouldn't need to supply quotient as a variant since quotient/remainder would work just as well. Only when you use special forms or procedures that take multiple values will the fact that the procedure does return more values work the same way as with Scheme. This makes values a better choice in CL than Scheme since you get away with writing one instead of more procedures.
In CL you can access a hash like this:
(gethash 'key *hash* 't)
; ==> T; NIL
If you don't use the second value returned you don't know if T was the default value or the actual value found. Here you see the second value indicating the key was not found in the hash. Often you don't use that value if you know there are only numbers the default value would already be an indication that the key was not found. In Racket:
(hash-ref hash 'key #t)
; ==> #t
In racket failure-result can be a thunk so you get by, but I bet it would return multiple values instead if values did work like in CL. I assume there is more housekeeping with the CL version and Scheme, being a minimalistic language, perhaps didn't want to give the implementors the extra work.
Edit: Missed Alexis' comment on the same topic before posting this
One oft-overlooked practical advantage of using multiple return values over lists is that Racket's compose "just works" with functions that return multiple values:
(define (hello-goodbye name)
(values (format "Hello ~a! " name)
(format "Goodbye ~a." name)))
(define short-conversation (compose string-append hello-goodbye))
> (short-conversation "John")
"Hello John! Goodbye John."
The function produced by compose will pass the two values returned by hello-goodbye as two arguments to string-append. If you're writing code in a functional style with lots of compositions, this is very handy, and it's much more natural than explicitly passing values around yourself with call-with-values and the like.
It's also related to your programming style. If you use values, then it usually means you want to explicitly return n values. Using cons, list or vector usually means you want to return one value which contains something.
There are always pros/cons. For values: It may use less memory on some implemenentations. The caller need to use let-values or other multiple values specific syntax. (I wish I could use just let like CL.)
For cons or other types: You can use let or lambda to receive the returning value. You need to explicitly deconstruct it to get the value you want using car or other procedures.
Which to use and when? Again depending on your programming style and case by case but if the returning value can't be represented in one object (e.g. quotient and remainder), then it might be better to use values to make the procedure's meaning clearer. If the returning value is one object (e.g. name and age for a person), then it might be better to use cons or other constructor (e.g. record).
I need to be able to read user input in scheme for a project. For example, I need to be able to read the string 4 5 * .. I was implementing it using the (read) function but it gives an error when it reads a .. I would use a different symbol but it is specified by the project description. Is there a way to do this?
You cannot use read to input arbitrary text. The read procedure is only meant for inputting "S-expressions", a data format that can be used to represent a superset of Scheme source code expressions.
The reason you cannot read a . via the read procedure is that a period token has a special role in Scheme source: it is used for dotted pair notation. (C1 . C2) is the way that the pair of C1 and C2 is written as an S-expression. Note there is a crucial difference between the single pair (C1 . C2) and the list (C1 C2) (which is made from two pairs); and yet the only difference between the source text is the presence/absence of a single period.
The dotted pair notation is described in section 6.3.2 of the R5RS.
So, as suggested in the comments on your question by Dan D., you should consider using the read-char procedure to consume user input text. It described in section 6.6.2 of the R5RS. It may seem counter-intuitive, since read-char only consumes a single character while read consumes many characters (and builds a potentially large tree of structured data), but the reality is that you can build your own parser on top of read-char, by invoking it repeatedly in a loop, as suggested by Dan D.
In fact, some scheme systems implement read itself by making it a Scheme procedure that invokes read-char. See for example Larceny's reader source code, where read will call get-datum, which calls get-datum-with-source-locations, which calls read-char in a number of places.
Alternatively, you might have other ways of reading input from the user. The read-line procedure is quite common (and its also easy to write on top of read-char). Or you might look into a Parser-Generator (like the one that generated the source code for Larceny's reader, linked above.
I used read to get a line from a file. The documentation said read returns any, so is it turning the line to a string? I have problems turning the string "1" to the number 1, or "500.8232" into 500.8232. I am also wondering if Racket can directly read numbers in from a file.
Check out their documentation search, it's complete and accurate. Conversion functions usually have the form of foo->bar (which you can assume takes a foo and returns a bar constructed from it).
You sound like you're looking for a function that takes a string and returns a number, and as it happens, string->number does exist, and does pretty much exactly what you're looking for.
Looks like this was answered in another question:
Convert String to Code in Scheme
NB: that converts any s-expression, not just integers. If you want just integers, try:
string->number
Which is mentioned in
Scheme language: merge two numbers
HTH