Return Styles: Pseud0ch, Terminal, Valhalla, NES, Geocities, Blue Moon.

Pages: 1-

Are there any high-level untyped languages?

Name: Anonymous 2012-02-06 17:01

See title.

Name: Anonymous 2012-02-06 17:10

lisp

Name: Anonymous 2012-02-06 17:27

>>2
Lisp is tagged, not untyped.

Name: Anonymous 2012-02-06 17:30

Grass the grass planting programming language.

Name: Anonymous 2012-02-06 18:22

>>1
See >>30

Name: Anonymous 2012-02-06 18:42

>>5
30 points to NULL. Looking at it is currently illegal.

Name: Anonymous 2012-02-06 21:53

untyped lambda calculus is higher order-level and uh... untyped

Name: Anonymous 2012-02-06 23:00

Name: Anonymous 2012-02-06 23:12

Forth

Name: Anonymous 2012-02-07 6:04

>>8
>missing a closing parenthesis

Name: Anonymous 2012-02-07 6:13

Anyone else feels that typing is single-handedly responsible for most of the complexity of imperative languages? I can see its use in huge projects, but even then Ada's self-defined types seem superior and safer. For the purpose of alignment all you need is to check the size of the variable.

Name: Anonymous 2012-02-07 6:33

>>10
It's a shiichan bug.

Name: Anonymous 2012-02-07 6:37

>>11
State is single handedly responsible for most of the complexity of imperative languages. Programs must constantly check the variables for sane values lest an unintended change in state results in an incorrect assumption in the logic.

Name: Anonymous 2012-02-07 6:46

>>11
I recently followed someone's advice on here, and I used void pointers for all my data types in C in a small project. Trust me, it didn't help reduce the complexity, and it made it around 80% more likely to segfault on the first run after typing some new code. It did save on typing, and because retrieval from structures was implemented with getter functions, it ended up looking a lot like scheme.

Name: Anonymous 2012-02-07 6:50

>>14
I recently followed someone's advice on here, and I used void pointers for all my data types in C in a small project.
10/10, thank you for starting my day with a smile!

Name: Anonymous 2012-02-07 6:58

>>13

this problem can be solved pretty effectively with modularity. As long as imperative functions look simple and predictable from the outside, things can remain pretty manageable for use. But if the function is 800 lines long, with loops in loops with continues and breaks all over, it will be very difficult to add additional features, or to effectively test every possible case the function is meant to handle. That tends to be easier in functional style, as the logic is more explicit. In imperative, it can become more compressed, and implicit, and many invariants are held in between the lines, or in between the statements.

Name: Anonymous 2012-02-07 7:06

>>15

No problem! Here have some code. I know I will never be able to use it for anything anyway:

tree.c

#include <malloc.h>
#include <assert.h>
#include <stdio.h>

#include "trace.h"
#include "utils.h"
#include "tree.h"

p tree_vtable[] = {
  (p)destroy_tree,
  (p)print_tree
};

v init_tree(p self, p item, p left, p right) {C
  P("init_tree: %p to ", self); PS(item); P(", "); PS(left); P(", "); PS(right); P("\n");
  init_object(self, tree_vtable);
  init_fields_tree(self, item, left, right);
R}

v init_fields_tree(p self, p item, p left, p right) {C
  P("init_fields_tree: %p to ", self); PS(item); P(", "); PS(left); P(", "); PS(right); P("\n");
  init(&((struct tree*)self)->item, item);
  init(&((struct tree*)self)->left, left);
  init(&((struct tree*)self)->right, right);
R}



p tree(p item, p left, p right) {C
  P("tree: "); PS(item); P(", "); PS(left); P(", "); PS(right); P("\n");
  p allocation = malloc(sizeof(struct tree));
  assert(allocation);
  init_tree(allocation, item, left, right);
R return allocation;
}

v set_left_tree(p self, p left) {C
  P("set_left_tree: %p to \n", self); PS(left); P("\n");
  set(&((struct tree*)self)->left, left);
R}

v set_right_tree(p self, p right) {C
  P("set_right_tree: %p to \n", self); PS(right); P("\n");
  set(&((struct tree*)self)->right, right);
R}

v set_item_tree(p self, p item) {C
  P("set_item_tree: %p to \n", self); PS(item); P("\n");
  set(&((struct tree*)self)->item, item);
R}

p left_tree(p self) {C
  P("left_tree: %p", self); P("\n");
R return ((struct tree*)self)->left;
}

p right_tree(p self) {C
  P("right_tree: %p", self); P("\n");
R return ((struct tree*)self)->right;
}

p item_tree(p self) {C
  P("item_tree: %p", self); P("\n");
R return ((struct tree*)self)->item;
}

v destroy_tree(p self) {C
  P("destroy_tree: %p", self); P("\n");
  unreg(item_tree(self));
  unreg(left_tree(self));
  unreg(right_tree(self));
R}

v print_tree(FILE* output, p self) {
  fprintf(output, "<tree>");
  fprintf(output, "<item>");
  print_object(output, item_tree(self));
  fprintf(output, "</item>");
  fprintf(output, "<left>");
  print_object(output, left_tree(self));
  fprintf(output, "</left>");
  fprintf(output, "<right>");
  print_object(output, right_tree(self));
  fprintf(output, "</right>");
  fprintf(output, "</tree>");
}

p merge_trees(p tree_left, p tree_right, int take_tree_right, p(*tree_constructor)(p,p,p)) {C
  P("merge_trees: "); PS(tree_left); P(", "); PS(tree_right); P(" %d\n", take_tree_right);
  if(!tree_left) {
    R return tree_right;
  } else if(!tree_right) {
    R return tree_left;
  } else if(!right_tree(tree_left)) {
    R return tree_constructor(item_tree(tree_left), left_tree(tree_left), tree_right);
  } else if(!left_tree(tree_right)) {
    R return tree_constructor(item_tree(tree_right), tree_left, right_tree(tree_right));
  } else if(take_tree_right) {
    R return tree_constructor(item_tree(tree_right), merge_trees(tree_left, left_tree(tree_right), 0, tree_constructor), right_tree(tree_right));
  } else {
    R return tree_constructor(item_tree(tree_left), left_tree(tree_left), merge_trees(right_tree(tree_left), tree_right, 1, tree_constructor));
  }
}

// The root will go down to the left. It's right child becomes the parent.
// The right child must not be null.
p rotate_left_tree(p root, p(*tree_constructor)(p,p,p)) {
  p right_root = right_tree(root);
  assert(right_root);
  return tree_constructor(item_tree(right_root),
                          tree_constructor(item_tree(root),
                                           left_tree(root),
                                           left_tree(right_root)),
                          right_tree(right_root))
}

// The root will move down to the right, with its former left child becoming the root's parent.
// The left child must not be null.
p rotate_right_tree(p root, p(*tree_constructor)(p,p,p)) {
  p left_root = left_tree(root);
  assert(left_root);
  return tree_constructor(item_tree(left_root),
                          left_tree(left_root),
                          tree_constructor(item_tree(root),
                                           right_tree(left_root),
                                           right_tree(root)));
}

int height_tree(p root) {
  if(!root) return 0;
  return max(height_tree(left_tree(root)), height_tree(right_tree(root))) + 1;
}

int size_tree(p root) {
  if(!root) return 0;
  return 1 + size_tree(left_tree(root)) + size_tree(right_tree(root));
}


Some things like inheritance became very elegant, but still, static typing can save you from a lot of segfaults in a language like C.

Name: Anonymous 2012-02-07 8:46

>>17
Is your code a joke or are you being serious?

Name: Anonymous 2012-02-07 8:52

>>18
just experimental. is it funny?

Name: Anonymous 2012-02-07 9:24

>>19
It's horrible

Name: Anonymous 2012-02-07 9:44

>>20
well, I never said the code wasn't horrible. Is the joke horrible?

Name: Anonymous 2012-02-07 9:50

>>21
You should feel bad for posting that shit.

Name: Anonymous 2012-02-07 10:10

>>22
Your criticism was bad and you should feel bad.

Name: Anonymous 2012-02-07 10:13

>>22
Well, it has gotten a rise out of you, so I feel rather satisfied actually.

Name: Anonymous 2012-02-07 22:23

I used void pointers for all my data types in C in a small project
TURBO SPEED PHP

Name: Anonymous 2012-02-07 22:28

>>25

Indeed. I suppose I could have just broken out my powerc compiler that didn't seem to be able to type check pointers.

Name: Anonymous 2012-02-08 0:22

>>11
If you're considering languages with type erasure, then no. There is a bit of added complexity to satisfy the compiler (especially in strongly typed languages) but that translates into elimination of a certain class of bugs. In weakly typed languages, like C, the class is narrower but there is virtually no complexity added, owing to the fact that you can void the type system at will. (Sure there's more characters on the line when you do unsafe casts, but they are there to remove complexity from the compiled code, not add it.)

If you're talking about dynamic languages there may be some added complexity. I keep finding Javascript is far too willing to creatively interpret things I'd rather be a bug (in the aforementioned class of bugs) or a far less intelligent coercion. These implicit conversions give types/operators loaded meanings based on context. (Some people will rip you a new one for overloading operators in type erased languages—this is part of the type system, and it does add complexity, but it's optional and hopefully rare enough. The important thing to remember is the type is necessarily predetermined at the call site in these languages.)

>>14,17
Bwahaha. I've made that dare (and threatened to do the same) at least once or twice on here. High-five.

>>16
I don't think you grasp the problem. It's the fact that you have action-at-a-distance. Just the other day I wrote a function to do nothing other than initialize a global variable and today I wrote a function to do nothing other than to access the contents of a different global. This is where state gets dangerous. I just realized there's a bug related in the first one (which would have been avoided if I structured the program differently, to avoid the global.) I am not sure about the second, I'll have to review it tomorrow.

Name: Anonymous 2012-02-08 1:17

>>27.2
***high five clap*** It was a good dare. I would have fun doing it again.

>>27.3
That's true. The only thing I was thinking of was spagetti code in long imperative functions with lots of nested loops, from the point of view of a quality assurance dude(te) trying to come up with a set of inputs to the function that will test each branch of code in the spagetti. But I don't know, maybe there is some equivalent horror in functional programming, as imperative code doesn't need to be spagetti.

Yeah global variables can be tricky. The most recent time I've used them was when communicating with generated C code. They can make decent, non-thread safe, dedicated, one way communicate channels between two other wise isolated parts of a program when it is impossible to get the two parts to talk to each other in a better way. But like you mentioned, they can often be avoided by using a different structure for the program.

Name: Anonymous 2012-02-08 18:12

>>28
There are corresponding challenges in FP, like threading state changes through the program can get verbose, as opposed to modifying it, i.e. side-effects. From what I understand Haskell goes to lengths to make this less inconvenient, where others will let you cheat.

I am put in mind of the decision to scrap the prover in BitC. The conclusion was that proving was unlikely to be taken advantage of by many developers and that it only buys confidence anyway. I feel that way about purity in FP, although it does buy a little more than confidence (some things are more efficient), but it also has a cost (some things are less efficient.) I don't feel that purity is law, but by default it is worth the price. The confidence it buys is quite high for the cost.

Name: Anonymous 2012-02-08 20:39

Forth and B (which is similar to C but only had a single type which later became int).
http://cm.bell-labs.com/cm/cs/who/dmr/kbman.html

Name: Anonymous 2012-02-09 2:41

>>29
yeah, there are many algorithms that depend on mutable state in order to obtain their run times. And there are many examples of applications where using only immutable data structures wouldn't be that great of an option. A good example would be a video game, where all entities need to be aware of changes made to other entities. This can be made functional by storing all entities in an environment data type, and making a full copy of the environment with added changes to the entities, every time the game advances a step. This sounds horrible, but it can be made efficient by double buffering the objects, IE, you have two allocated environments, and upon every tick, you swap which one is in use, assigning the new state into the previously unused one, while referring to the previously used environment to construct the new entities. A typical imperative solution would be to iteravely call an update function on every entity in the environment, modifying each in place. This can create strange effects though, as the order in which the update function is called on the entities can cause strange effects. Like, say characters A and B were to punch each other hard in the face, at the exact same time. Using the functional approach, both A and B in the next state would be knocked out, because they were punched by B and A in the previous state respectively. In the in place modification approach, say A's update function is called first, and A punches B out cold. Then when B's update function is called, B is unconscious, and no longer able to knock out A. So the results differ. This effect can be made less significant by maintaining a high frame rate, as interesting things are less likely to happen at the same time, but in some other applications there is no way to get around it. IE, there are sometimes dynamic interactions that occur in every frame, and the order of application of the update function can cause very strange artifacts in the simulation.

Name: Anonymous 2012-02-09 3:52

>>31
Generally this is resolved through a system called priority. Every action is assigned a value that is compared to the value of all other actions that occured within the smallest time unit. Then every set of actions with priority X, starting at 0 and going up to the highest value of X, is resolved simultaneously - or rather, the result mimics a simultaneous result. This, however, mandates multiple passes over the same entities and so is at the best case twice as slow.

The two environment approach sounds pretty interesting and similar to some techniques involving reflection.

Name: Anonymous 2012-02-09 15:03

Why can't one use a turn system or a MCV pattern if you will.
First at the frame everyone commits to an action. Then there is a logic turn where logic code checks whcih actions was choosen by objects and then use gamelogic to determine what to happen, then sets varaible and or message the frame system what the result is.

Name: Anonymous 2012-02-10 1:00

>>33
Yeah that could work. I suppose in the A and B punching each other example it would be something like:

1. A plans to punch B out.
2. B plans to punch A out.
3. A tells B that B will be knocked out in the next frame (both A and B can have sets of events that will happen to them in the next frame. In this case, A adds the GetKnockedOut event to B's event set).
4. B adds GetKnockedOut to A's event set.
5. All communication is done, and now each entity executes their event collection.
6. A executes GetKnockedOut. A is unconscious.
7. B executes GetKnockedOut. B is unconscious.

>>32
interesting. It makes sense that certain events would be more important than others.

Name: Anonymous 2012-02-10 4:00

I am 33 and i have though about the problem. The problem is not that they can knock out each other at the same time. The problem is the simplified states we are using. We are implicitly assuming that a character can atleast be conscious or unconscious with the latter state limiting the actions of the charcter.

What instead if our game modeled the values of the arm. Like length, weights, speed, acceleration, mass and direction. Thus when the gameengine detects a collision between the arm and the character b head code to transfer the Force begins to execute. And thus the effect this will have on character b, eventually leading to falling down motion/animation. But in the same time charcters b arm will still be in motion since it is modelled as real world physic and it does not matter if character b in unconscious or conscious since the arm will have its own (relativly to the body ofcourse) momentum.

Name: Anonymous 2012-02-10 4:35

>>35

Yeah, I choose the discrete state changes to make the difference very obvious. Making the simulation more realistic by modeling the collision of the physical bodies would make the effect less obvious, but it would still be there. You could imagine, A's fist smashing into B's face, so hard that B's head flys back, pulling B's body along with it, which pulls on B's arm, which lessens the velocity of B's fist, making it's impact on A's face less severe. The order of the update calls in that case may have been:

1. update A's fist.
2. update B's face.
3. update B's chest.
4. update B's arm.
5. update B's fist.
6. update A's face.
7-rest. update what's left, in some order.

But we could have chosen to update B's fist first, and A's impacted body second, and B's face third, resulting in a scenario that benefits B instead.

What's going on here, is that when the objects collide, they cause each other's velocities to change. And these velocity changes will cause future collisions calculated in the same frame to be different. Whenever the new state overwrites data used in the calculation this effect will occur. It is safe if the new state is disjoint from the input. One example would be positions and velocities in a simulation with n bodies, pulling on each other with gravity. In each frame, a force is applied to each object. The force acting on each object is determined completely by the objects' relative positions. But the force does not directly change the object's positions. It instead exerts a force, which is converted to an acceleration, which changes their velocities. Because the update function reads only position information, and writes only to velocity information, it is safe to call the update function in place on the bodies, in any order. As far as the update function is concerned, an object looks exactly the same, whether it has been accelerated in that frame or not, because it hasn't moved yet. You would then need to have a second position update function, that adds a time scaled velocity to the current position.

Name: Anonymous 2012-02-10 6:51

One way to lessen the effect is to use a faster update rate, so that when the hit takes it takes lets say 10 updates for the force to progress so that the arms of charcter b recives a lower force.

So with that system if they both hit the same time it won't immeadtly lower the force of the arm since it might take 2-10 updates before that force has had effect. 

Or to simplify things my previous version with a game logic turn will work.

Yes your idea is good, it appeared we have achieved similar conclusions. The force must not be immeadly applied.

Don't change these.
Name: Email:
Entire Thread Thread List