XML

kent logo

CO538 Anonymous Questions and Answers

This page lists the various questions and answers. To submit a question, use the anonymous questions page. You may find the keyword index and/or top-level index useful for locating past questions and answers.

We have taken the liberty of making some minor typographical corrections to some of the questions as originally put. Although most of the questions here will have been submitted anonymously, this page also serves to answer some questions of general interest to those on the course.

When asking questions, please do not simply paste in your code and ask what is wrong with it, as these types of question are hard to answer in a public forum (resulting in either no answer, or an answer which will only be of use to the person asking the question). In many cases, a question about code can be formulated in general terms. For example, if you have an `IF' block that results in an `incorrect indentation' error, you might ask, ``what is the correct syntax for an occam `if' statement ?''. Questions of this form are easier to answer, and are meaningful to all.

Questions that are not suitable for these public pages (i.e. those that contain assignment-specific code), should be mailed to your seminar-leader.


Question 21:

Submission reference: IN2051

Same problem as in Question 18 (2011):

    pause(1000000)

results in waiting about 30 seconds. I am using the Transterpreter on Windows 7 64-bits.

Same waiting time with:

    TIMER tim:
    INT timeout:
    SEQ
      tim ? timeout
      timeout := timeout PLUS 1000000
      WHILE TRUE
        SEQ
	  tim ? AFTER timeout

In order to have about a delay of 1 second, I need pause(33333). But ... pause(1000000) in print.streams does give 1 second.

Answer 21:

I suspect your code ... please send to Fred <frmb@kent.ac.uk>. We won't tell you what's wrong ... but will point to any areas of obvious concern!

Keywords: q4


Question 22:

Submission reference: IN2052

Hi, I'm having some problems with negative numbers and IF statements. For example, if I have the following statement:

    IF
      x = 1
        x := -1
      TRUE
        x := 1

The compile throws no problems, and the program works okay (ish but for other reasons), importantly it does use "x" as a negative number. However if I flip this around to...

    IF
      x = -1
        x : = 1
      TRUE
        x := -1

I get:

    Error-occ21-/..{directory}../src.occ(428)- expected operand, found "-"

I don't understand why I can use the negative symbol in that context in the assignment, but not in the IF statement?

Answer 22:

This is quite a common problem, but straight-forward enough solution. When you write "-x", for instance, you're actually applying the unary minus operator to "x". Same as when you write "-1", where you're applying the minus operator to the constant 1 (one) instead. This is an expression ... so, when it appears as part of another expression, it must be bracketed.

An assignment has the form "l-value := expression". So, if the whole expression is "-1", it needs no bracketing.

In an "IF" construct, each condition is its own expression (with boolean value). Now, the whole of "x = -1" is such an expression (very different from an assignment) and, to be correct, needs bracketing, i.e. "x = (-1)".

It may seem slightly silly, as there is no misinterpretation possible in that case; but consider something like: "-x + 42". Should that mean "(-x) + 42" or "-(x + 42)"? Being explicit about what you mean is good programming practice, hence the need for bracketing sub-expressions :-).

Keywords: negative-numbers


Question 23:

Submission reference: IN2053

I am at the point where I have an implementation of speed.control. However, pressing any of the monitored keys in rapid succession causes a deadlock. Is this to be expected?

Answer 23:

Probably not — it hints at problem in the design of your solution. Without seeing the code, my immediate thought is to wonder if you have some components polling their control channels, e.g.:

    WHILE TRUE
      PRI ALT
        BOOL any:
        control ? any
          ...  do something useful
        SKIP
          SEQ
            in ? any
            ...  other stuff

Although it takes more than just this, you could end up in a situation where the code above is stuck waiting for data from "in" or a subsequent output, but some other component in the network is stuck trying to send data down the "control" channel, and as a result, is stopping the input (or output) in the above code from happening.

Check for cycles of connected processes in your solution and look for deadlock possibilities in there.

Keywords: q4


Question 24:

Submission reference: IN2055

Were the ASCII network diagrams provided in each source file generated by a tool? Perhaps `graphvis`? If they were done by hand, that is a truly valiant effort :).

Answer 24:

They were done by hand ;-). We're quite adept at churning these out so it doesn't take too much time!

Keywords: diagrams


Question 25:

Submission reference: IN2054

To partially answer my own question (invalid reference to another question!); the deadlock seems occur arbitrarily whenever the output lines per second is > 32. I was running the program directly from vim (!./q4), which I presume buffers and can't output quick enough?

There is no deadlock if I run the program directly from the terminal (urxvt).

Answer 25:

That is slightly odd — even if vim doesn't take the output quickly, it should just stall the program, not deadlock it completely. KRoC does behave slightly differently if the standard I/O isn't a terminal, but without investigating I'm not sure how vim implements this (i.e. whether it just uses pipes or whether it opens a VT pair for communication).

PHW adds: I just tried running the model answer in the way described (from vim) ... and it works just the same (i.e. correctly) as when run directly.

Keywords: q4


Question 26:

Submission reference: IN2056

I am having trouble implementing the "pairs2" process for the 3rd assessment. Below is what I have so far, but it doesn't work:

    PROC pairs2 (CHAN INT in?, out!, inject?)
      INITIAL BOOL flip IS FALSE:
      WHILE TRUE
        PRI ALT
          INT injected:
          inject ? injected
	    flip := NOT flip
          SKIP
	    CASE flip
	      FALSE
	        pairs (in?, out!)
	      TRUE
	        differentiate (in?, out!)
:

Answer 26:

Please never show someone your code and ask why it doesn't work! Instead, explain why you think it does work – i.e. talk through the code, saying what you are expecting it to do and saying why. Nine times out of ten, either yourself or the person to whom you are explaining will then see why what you are saying is wrong: some unfounded assumption you have made or something wrong with the mental model you have about the ideas/constructs you are using.

The problem here is that once either "pairs" or "differentiate" is instantiated in the above code, it never terminates (because its components all have infinite loops). This is the mistake in your mental model of what is happening here. As a result, the loop in your "pairs2" above will never loop! As such, any attempt to communicate on the "inject" channel after either "pairs" or "differentiate" has been started (and that will be within nanoseconds of the start of your system) will not be accepted and your "keyboard.monitor" will be forever blocked. Your system should still be running ... but you have lost control.

The correct way to go about this is to change something inside the existing "pairs" process, rather than trying to replace the whole thing. However, if you can't figure out that particular solution, you can have both "pairs" and "differentiate", but running in parallel, with a switch process at the front (which sends data to one or the other) and a simple multiplexer component at the other side which collects output from both. However, that's a rather heavyweight solution, but at least it works!

Keywords: q4


Question 27:

Submission reference: IN2057

I'm on the last section of assessment 3, when I go to output a 'bell' on the error channel, I get the message "illegal character, ASCII 123", what can I do to resolve this please?

Answer 27:

ASCII 123 is the opening brace character — make sure you don't have that floating around your program (it's an illegal character in the occam-pi language).


Question 28:

Submission reference: IN2059

Hi, I'm really struggling with the speed.control section. I have a process that takes 1s and 0s given to it by my monitor, and then sends then either halves them, or doubles them depending on what is received. This is then sent to another process which takes a value from the speed.control process, and outputs a line of digits. After doing this, it checks with a timer to see if the time figure is greater than speed. If it is, it waits until the timer has again passed the speed value. The problem is, when I key plus or minus, nothing seems to happen? Any thoughts on where I've gone wrong?

Answer 28:

I don't understand what you means by "either halves them, or doubles them depending on what is received"? You say your process is receiving 0s and 1s, presumably these are INTs? But if so, halving a 0 or a 1 gets 0, doubling a 0 gets 0 and doubling a 1 gets 2. I don't understand how that helps ...

You also talk about comparing a "time figure" with a "speed" ... which is like comparing chalk with cheese. You should only compare time values against time values (which may have been calculated from a previous time value and a gap interval). For example, the gap interval (in microseconds) for a speed of 256 lines per second would be 1000000/256.

Hope this helps ...

Keywords: q4


Question 29:

Submission reference: IN2060

its cutting it a bit fine i know, but how do i ipmlement the speed control section for the last part of the assigemtn, ive been sticuk on thisfor ages, ive fiigured out that i need to use a timer, im just not sure how best to utilize it.

Answer 29:

I'm afraid you have to ask questions a little more specific than: "how do I do this part of the assignment?".

However, we will say this ...

The model answer has two versions for speed.control. Version 0 uses only the pause(delay) procedure to control output line speed: it has to respond to speed control signals and, of course, the data flow it's controlling. It is very simple but has some not good properties (such as not being able to respond promptly to speed-up signals when executing a long pause). Nevertheless, it would get good marks, :).

The other version uses TIMERs directly and responds quickly to speed-control signals at all times – but it's a bit more complex.

Keywords: q4


Question 30:

Submission reference: IN2061

Hello there, I am wondering; is it possible to use an id-like process to link two channels of the same protocol without having to read the data from the protocol by yourself and re-send it along?

Answer 30:

Connecting two (same-protocol) channels with an id-like process yields a buffered channel with capacity 1. The CSP library for Java (JCSP) provides for the construction of occam-like (i.e. unbuffered) channels by default, but also for buffered channels of any capacity (including infinite) and varying kinds of buffering (blocking, like Choices slide 105, overflowing, slide 107, or overwriting, slide 108). At some time, it would probably be good to introduce this into occam-pi – it would be more convenient, safer and more efficient for the compiler to construct such buffering than the programmer.

A second point raised by your question is that of generics. It would be nice to be able to parametrise the types of messages carried by channels plugged in to processes that don't care. For example:

    PROC id <TYPE P> (CHAN P in?, out!)
      WHILE TRUE
        P m:
        SEQ
          in ? m
          out ! m
    :

Instances of such a generic process would have the obvious form – e.g.

    id <REAL64> (a?, b!)

which would instance an id process for channels carrying double-precision floating-point numbers.

However, defining the above idea is complicated by the current concept of message PROTOCOLs in occam-pi (see the Protocol slides, not yet covered in the course). It should probably wait for a more powerful type system for occam-pi (that is planned).

You are also asking, I think, for a syntactic sugaring that saves "having to read the data from the protocol by yourself and re-send it along"? Perhaps, something like:

    PROC id <TYPE P> (CHAN P in?, out!)
      WHILE TRUE
        out ! (in ?)
    :

or maybe:

    PROC id <TYPE P> (CHAN P in?, out!)
      WHILE TRUE
        in? > out!
    :

It's a thought! See also Question 56 (2010).

However, for all forms of engineering (such as language design), always consider Occam's Razor: "Numquam ponenda est pluralitas sine necessitate", which roughly translates to "Don't invent things you don't need" or "keep it as simple as possible". For programming languages, this means only adding mechanisms that are really needed ... where real need covers new ideas (that let us do useful things we couldn't do before) and more powerful forms of expression (that let us do common things more easily than we did before). We have to work hard to honour this principle. Software engineering constructs virtual artifacts – unconstrained by limits imposed by the physical world. As such, it's only too easy to build something complex that doesn't quite do the job ... than something simple that does.

Keywords: generics , protocol , occam , razor


Question 31:

Submission reference: IN2062

Looking at the suggested plan for q7, paragraph (6) mentions: "This may be tricky for fork messages: e.g. it should say the fork number and which phil is holding it".

Does this mean it should print: "Fork 4 picked up by Philosopher 1"?

Or just: "Fork 4 held by right philosopher"?

If it's the former, I can't work out how to do that without editing quite a bit of code.

Answer 31:

It's the former. You will have to know which actual philosopher has picked up that fork later – when you animate the event (rather than just talk about it, which is this initial stage).

If you find you are editing lots of code, there is something wrong with your code. Marks will be lost for code that has repeated sections of logic that are different only in the magic numbers they contain. Make sure you are not doing that! To avoid that, you need some simple algebra involving id-numbers and, when you get on to the animation, some coordinate tables (i.e. VAL [5][2]BYTE arrays). Except, of course, that 5 should be named (e.g. n.phils). The 2 I will allow as it's the number of dimensions in your screen coordinates and is unlikely to change (unless you escalate to a 3-D animation!).

For the question you raised, look at slide 29 of Applying. The philospher that picks up fork id on its left channel is philospher id. The philospher that picks up fork id on its right channel is philospher (id + 1)\n.phils. Simples!

Keywords: q7

Referrers: Question 33 (2012) , Question 33 (2012) , Question 33 (2012)


Question 32:

Submission reference: IN2063

For the Dining Philosophers assessment, should philosophers wait a new random amount of time each time they think or eat, or set one before their loop begins?

Answer 32:

The former – the wait times should be (randomly) different for each wait for each philosopher.

Keywords: q7


Question 33:

Submission reference: IN2066

Given a string "msg", can I create a second string "underline" that is composed of repeating characters of size "msg"? E.g. in Python:

  a = "hello"
  b = "=" * len(a)
  print(a + "\n" + b)

produces:

  hello
  =====

Answer 33:

Yes:

  VAL []BYTE a IS "hello":
  SEQ
    out.string (a, 0, screen!)
    out.ch ("*n", 0, screen!)
    out.repeat ('=', SIZE a, screen!)    

Keywords: q7


Question 34:

Submission reference: IN2064

Hi, is is possible to have channels, both shared and normal in a RECORD? I have this:

  CHAN TYPE foo
    MOBILE RECORD
      CHAN INT x?:
      CHAN INT y?:
  :

but this doesn't compile when used with SHARED CHANs. Is there a way of doing this, or do I just need to pass the SHARED CHANs individually, as it doesn't seem possible to have an array of them either?

Answer 34:

Fields of a CHAN TYPE RECORD (informally known as channel bundles) can only be CHANs (with field names that specfify the direction of use) – so the direct answer to your question is: no. However, ...

We only declare variables for the ends of such bundles of channels. The type names of these ends are the type names of the bundles, Bundle type ends with the "!" specifier mean that their channel fields must be used in the opposite directions to those declared in the bundle type (they are the opposite ends of the bundle). Note: it's the the type of the bundle ends that carry the "?" or "!" specifiers – not the variables that hold them (whereas, for standard CHANs, direction specifiers go with the channel variables; we apologise for this inconsistency).

Now, bundle type ends (i.e. either end of the whole bundle) may be SHARED, which should give you what you were after (I hope). Many processes may be given the same end of a shared bundle of channels. To use them, just CLAIM the bundle-end variable and use the individual channels as you like (in the correct directions, of course). See the Mobiles slides 39-43 for examples.

Note: the material on these these channel bundles is not an examinable part of this module.

Re. your question about arrays of shared channels (ordinary ones): sorry, these are not supported – see Question 30 (2010). However, arrays of shared ends of channel bundles are supported, :).

Keywords: shared-channel , chan-type


Question 35:

Submission reference: IN2067

Although we were never introduced to occade, do you have any tutorials on making occade work for simple background and sprites? I have looked at the library and have no idea how to use it.

Answer 35:

See the "occade" questions listed in the keyword index (linked at the top of each of the Q&A pages). You may find Question 46 (2009) a good place to start. Mail us if you want further help.

Keywords: occade


Question 36:

Submission reference: IN2068

This question is related to the mars project.

Upon trying to complete task 2, I have hit a wall in which when trying to read from the array of channels hazard to an array of INTs. I recieve the error message:

  "Error-occ21-mars-main.occ(83)- hazard subscripted too many times" 

The following code fragment is what I have attempted to do:

  ...  code omitted

Answer 36:

Your code has a BOOL variable named hazard, declared in the scope of an array of channels also named hazard. With multiply declared names, only the most recent one is used. Your code has a replicated ALT trying to read from the channel array ... but all the compiler sees if the boolean variable ... which doesn't have subscripts!

Fix: choose a different name for your boolean!

Keywords: mars


Question 37:

Submission reference: IN2069

This question is related to the dining philosophers project. Currently as it stands the philosophers and forks individually print to the screen when claimed ("thinking, eating, on.table, left.held, right.held") and the security prints the number of philosophers sitting. Theoretically this works however, I am having issues making the philosophers behave randomly as at the moment they do indeed act randomly but the process is rendering really fast for anything to be visibly coherent.

I am using the pause (INT delay) process used in previous exercises to cause the thinking and eating delays, but making this random and at a speed comprehensible is difficult and something I cannot seem to gain.

The following code fragment is from my philosopher process up to claiming the shared report channel to think:

  ...  code omitted
  thinking, s:= random (15, s)
  ...  code omitted
  pause (thinking)
  ...  code omitted

Answer 37:

Your call to random returns a pseudo-random integer between 0 and 14. Your call to pause with that value means a delay of somewhere between 0 and 14 microseconds! Try:

  thinking, s:= random (15*SECONDS, s)

where:

  VAL INT SECONDS IS 1000000:

Keywords: random , q7


Question 38:

Submission reference: IN2065

I have connected up my dining philosophers processes and am showing an animation on the screen (hurrah).

However, the reporting of my fork process appears to be running in a strange order. It often reports that it has been picked up on the right before reporting that it has been put down on the right (and vice versa).

I haven't edited the code other than to add in reporting (for both pick up and put down), so I find it odd that this is happening. It seems to me that the display process is simply receiving the reports out of order, rather than anything wrong with the fork process.

Any thoughts as to why this might be the case?

    [snip sensible looking code]

Answer 38:

The code looks fine, i.e. you have something like this (for the benefit of others) in the fork:

    ALT
      left ? any
        SEQ
          ... report fork picked up
          left ? any
          ... report fork put down
      right ? any
        SEQ
          ... report fork picked up
          right ? any
          ... report fork put down

And the display process looks like it's flushing the output appropriately. I don't think the problem is in the way you're reporting, but it may be in what you're reporting. Your reporting here attempts to engineer a philosopher ID from the fork ID, which is bad practice in my view — if the forks and philosophers were reconnected in "secure.college", things would change in less than obvious ways. Double-check that the values emitted by the fork to the display make sense given the philosopher in question. Getting that wrong could easily produce the symptoms you're seeing. It cannot be the case that the reports for a single fork arrive out-of-order since the reporting order is in SEQ.

If you need to know which philosopher is picking-up/putting-down a particular fork, I don't see any harm in changing the "BOOL" signals to "INT"s for the fork-philosopher interaction.

Keywords: q7


Question 39:

Submission reference: IN2070

I have followed the plan and have a shared channel, but it seems I can't achieve parallel output of the animation when reports only come in sequence...

My security guard's counter always seems to be out of sync with the actual number of philosophers at the table, but I'm unsure why. Any ideas how to achieve this?

Answer 39:

For the first problem, you may want to consider adding additional processes to help control the animation. Clearly having all the animation handled by "display" which has a single input channel from everything isn't going to work (as you say, it's serialised). What you would need to do is introduce helper processes which do the legwork of the animation and only communicate step-by-step animation actions to the "display" process. That way lots of things can be animating at once without a problem.

As for the issue about the security guard counter, are you flushing the output after writing the integer to the screen? If not, it may be stale. If that's not the problem, try mailing your code to your seminar leader who should be able to spot the problem quickly.

Keywords: q7 , shared-channel , animation

Referrers: Question 44 (2011)


Question 40:

Submission reference: IN2071

Since strings within a list have to be padded (see Question 104 (2003)), I'd like to keep track of the actual length of a string (sans padding).

For example:

    "Cherry Tree": 11
    "Cuban	": 5
    ...
    "Lady Luck	": 9

Now, I believe 3D arrays are one way to achieve this. 2D arrays blow my mind far enough, but 3D takes it to the next level of discombobulation!

This feels like it should work:

    VAL [][][]BYTE a IS [["Cherry Tree", [11]], ["Cuban      ", [5]]]:

... but woefully gives me:

    table elements are of different types

What am I missing? Can it be simplified?

Answer 40:

The issue here is that "[11]" is of type "[1]BYTE", rather than of type "[11]BYTE". The simplest method (in my view anyhow) is to use a RECORD type (which we've now covered in the lectures) along the lines of:

    VAL INT MAX.STRING.LEN IS 128:

    DATA TYPE MY.STRING
      RECORD
        [MAX.STRING.LEN]BYTE str:          --* string data.
        INT len:                           --* actual length of string.
    :

Then you can easily create an array of these things:

    [42]MY.STRING string.table:

You'll probably want some helper PROCs to manage and display these sorts of things, but that's trivial enough:

    PROC set.my.string (MY.STRING s, VAL []BYTE str)
      SEQ
        IF
          (SIZE str) > MAX.STRING.LEN
            s[len] := MAX.STRING.LEN
          TRUE
            s[len] := SIZE str
        [s[str] FOR s[len]] := [str FOR s[len]]
    :

    PROC out.my.string (VAL MY.STRING s, VAL INT padding, CHAN BYTE out!)
      out.string ([s[str] FOR s[len]], padding, out!)
    :

Both of the above bits of code use array slices which haven't been covered in the lectures yet, but their operation is largely straightforward :-) — feel free to read up on them; they're at the end of the Shared-etc. slides.

Keywords: q7 , strings , string-handling

Referrers: Question 42 (2011)

Valid CSS!

Valid XHTML 1.0!

This work is licensed under a Creative Commons Attribution-Share Alike 3.0 Unported License.
Last modified Mon May 20 13:50:22 2013
This document is maintained by Fred Barnes, to whom any comments and corrections should be addressed.