Yathi
Yathi

Reputation: 1041

Unable to understand TCL proc inputs

Hi I am trying to understand a part of code which is written by someone else. This is the definition of the proc:

proc defState {state_id attribute object_id value place args} {
     global state_list state_objs state_attr_vals state_attr_id
# Build up record of defined states and perform error checking
if {[member $state_id $state_list]} {
    put-error "ERROR: State $state_id is being defined twice"
    #exit-steve
}
set state_list "$state_id $state_list"
if {![info exists state_attr_vals(${object_id},${attribute})]} {
set state_objs($object_id) $place
    set state_attr_vals(${object_id},${attribute}) $value
} elseif {[member $value $state_attr_vals(${object_id},${attribute})]} {
put-error "WARNING: Multiple states with same object/attribute/value: $state_id"
} else {
set state_attr_vals(${object_id},${attribute}) \
    "$value $state_attr_vals(${object_id},${attribute})"
}
set state_attr_id(${object_id},${attribute},${value}) $state_id

defSteveText $state_id goal "this should be generated by NL"

sp "top-ps*elaborate*state*add-to-current-state*$state_id
  (state <s> ^problem-space.name top-ps
             ^current-state <cs>)
  -->
  (<cs>  ^${state_id} <obj> + &, <n-obj> + &)
  (<obj> ^id $state_id ^name $state_id
         ^type state
         ^polarity positive
         ^object-id $object_id
         ^attribute $attribute
         ^value $value
         ^negation <n-obj>)
  (<n-obj> ^id $state_id ^name $state_id
           ^type state
           ^polarity negative
           ^object-id $object_id
           ^attribute $attribute
           ^value $value
           ^negation <obj>)"

;##### START TEMP GLUE #########
sp "top-ps*elaborate*state*test*goal*$state_id*positive
  (state <s> ^problem-space.name top-ps
             ^current-state <cs>
         ^io.input-link.perception <p>
             ^mental-state <m>)
  (<cs> ^${state_id} <pos>)
  (<pos> ^polarity positive
         ^negation <neg>)
  ($place ^${object_id}_$attribute $value)
  -->
  (<neg>  ^satisfied false + <)
  (<pos>  ^satisfied true + <)"

sp "top-ps*elaborate*state*test*goal*$state_id*negative
  (state <s> ^problem-space.name top-ps
             ^current-state <cs>
         ^io.input-link.perception <p>
             ^mental-state <m>)
  (<cs> ^${state_id} <neg>)
  (<neg> ^polarity negative
         ^negation <pos>)
  ($place ^${object_id}_$attribute \{<val> <> $value <> *unknown* \})
  -->
  (<pos> ^satisfied false + <)
  (<neg> ^satisfied true + <)"

sp "top-ps*elaborate*state*test*goal*$state_id*unknown
  (state <s> ^problem-space.name top-ps
             ^current-state <cs>
         ^io.input-link.perception <p>
             ^mental-state <m>)
  (<cs> ^${state_id} <neg>)
  (<neg> ^polarity negative
         ^negation <pos>)
  ($place ^${object_id}_$attribute *unknown*)
  -->
  (<pos> ^satisfied unknown + <)
  (<neg> ^satisfied unknown + <)"

global simulator_name
set sim_state ${object_id}_$attribute
if {[send $simulator_name "memberp ${sim_state} \$SceneAttributes"]} {
#echo "$state_sim already defined"
} else {
send $simulator_name "defSceneAttr $sim_state $sim_state symbol"
}
;##### END TEMP GLUE #########

And the implementation of the proc is given as follows:

defState bird-safe            health bird healthy <p> \
   :concerns {{sgt 25.0}} \
   :initialize *unknown* \
   :probability 0.55  \
   :sim-object *none*

So what I do not understand is how does 'health', 'bird' and 'healthy' in the defState implementation corresponds to the variables in the proc definition.

And what is 'p' there?

I understand that it might be a confusing and probably vague question. But if anyone can help me that would be really great!

Thanks.

Upvotes: 1

Views: 160

Answers (1)

Jerry
Jerry

Reputation: 71538

Well, if that's all there is to the proc, there's not much going on.

You are passing some arguments to the proc, which accepts 5 'standard' variables:

  1. state_id

  2. attribute

  3. object_id

  4. value

  5. place

and any more variables on top of the 5 first will go in args.

When calling the proc, you are passing those strings into the variables above:

  1. bird-safe

  2. health

  3. bird

  4. healthy

  5. <p>

  6. :concerns {{sgt 25.0}} :initialize *unknown* :probability 0.55 :sim-object *none*

Of course, since $args is a list, you will get those elements if you enumerate them:

  1. :concerns

  2. {sgt 25.0}

  3. :initialize

  4. *unknown*

  5. :probability

  6. 0.55

  7. :sim-object

  8. *none*

Thus, in the proc, you will have the above strings in the variables I listed earlier. You can see them if you use puts within the proc, and the results would be:

puts $state_id   ;# gives => bird-safe
puts $attribute  ;# gives => health
puts $object_id  ;# gives => bird
puts $value      ;# gives => healthy
puts $place      ;# gives => <p>
puts $args       ;# gives => :concerns {{sgt 25.0}} :initialize *unknown* :probability 0.55 :sim-object *none*

By default, variables are separated by space (the number of spaces doesn't matter, so I'm a bit confused as to why there's so much space between bird-safe and health), and it should be easy to see how each string gets into which variable.

global is used to enable the use of variables existing in the global namespace or make local variables (those created in the proc) available to the global namespace. in your example, it is doing this for four variables: state_list, state_objs, state_attr_vals and state_attr_id.

For instance, if the variable state_list exists in the global namespace, you will be able to access it within the proc. Without global state_list being mentioned, you will get an error saying that the variable state_list doesn't exists if you try to use it.

As for what is <p>, well, it's just a string for what has been described in your question and nothing meaningful with limited information.


As per the addition to your question, you are calling other functions in the #TEMP GLUE# part. For example, you will first have the substitution of variables, meaning this:

sp "top-ps*elaborate*state*test*goal*$state_id*positive
  (state <s> ^problem-space.name top-ps
             ^current-state <cs>
         ^io.input-link.perception <p>
             ^mental-state <m>)
  (<cs> ^${state_id} <pos>)
  (<pos> ^polarity positive
         ^negation <neg>)
  ($place ^${object_id}_$attribute $value)
  -->
  (<neg>  ^satisfied false + <)
  (<pos>  ^satisfied true + <)"

Will become this (I added ;# ^^^ to show the substitutions):

sp "top-ps*elaborate*state*test*goal*bird-safe*positive
;#                                   ^^^^^^^^^
  (state <s> ^problem-space.name top-ps
             ^current-state <cs>
         ^io.input-link.perception <p>
             ^mental-state <m>)
  (<cs> ^bird-safe <pos>)
;#       ^^^^^^^^^
  (<pos> ^polarity positive
         ^negation <neg>)
  ($place ^bird_health healthy)
;#         ^^^^ ^^^^^^ ^^^^^^^
  -->
  (<neg>  ^satisfied false + <)
  (<pos>  ^satisfied true + <)"

Do you see how $state_id became bird-safe, ${object_id}_$attribute $value became bird_health healthy? The value of those variables were all defined at the beginning of the proc.

Note that ${abc} is basically the same as $abc. The advantage of using ${abc} is that you can specify the exact variable name.

If you have a variable named abc with value xyz and use $abc_d to output xyz_d, tcl will look for the variable abc_d and say that the variable abc_d doesn't exists.

By using the braces, you explicitly tell Tcl that the variable name is abc instead of abc_d.

Upvotes: 2

Related Questions