TweetFollow Us on Twitter

OOP MacForth
Volume Number:3
Issue Number:2
Column Tag:OOPS in Forth

Object Oriented Programming for MacForth

By Paul Snively, Contributing Editor, ICOM Simulations, Inc.

OOPS.

They're getting to be all the rage.

The Macintosh design was based on one. There are several available for a wide variety of hardware. Some are OOPS through and through, others are just OO extensions to existing languages.

Welcome to OOPS, the column dedicated to Object-Oriented Programming Systems for the Macintosh .

It's hoped this column will evolve into a comprehensive look at object-oriented programming on the Macintosh. For now I will focus my efforts on two languages, one of which has had a vast impact on people's understanding of object-oriented programming and supports a tool that makes standard Mac user-interface support much easier. The other is only of interest to die-hard FORTH programming freaks like myself.

The first language is Object Pascal, and the second can be either Neon or ForthTalk. ForthTalk is a new product which I just received, and I already like it much more than I like Neon. We'll get into Object Pascal, either TML or MPW, next time.

ForthTalk

ForthTalk is a $55 extension to the MacFORTH programming language that adds capabilities to the system generally described as "flavors," a term I believe, if memory serves correctly, was borrowed from Common Lisp. (Incidentally, one of my pet peeves is that even object-oriented programmers don't seem able to agree on a standard terminology to describe their system's capabilities. I want to know exactly what is wrong with Smalltalk's terminology of Classes, Subclasses, Superclasses, Instances, and Methods. One answer, that few object-oriented languages offer multiple inheritance, and "flavors" provides an intuitive framework in which to discuss that capability, will be discussed in a moment).

ForthTalk is distributed on two disks. The first disk contains the tools to create the ForthTalk Kernel. These include the "Token Resizer" (for expanding the number of definitions that MacFORTH can handle) and the "ForthTalk Loader", along with a slightly reworked copy of the "FORTH Blocks" file and a copy of the standard MacFORTH block file editor. The second disk is the library disk. It contains the source code to the "Vanilla" flavor (analogous to Smalltalk's "Object" class) plus a few more useful flavors, source code to the tutorial in "Chapter 1," plus source code files to a couple of demos that aren't described step-by-step within the documentation.

ForthTalk is an extension to the current version of the MacFORTH kernel (which, as of this writing, is K2.4). This means you must be a licensee of MacFORTH K2.4 from CSI in order for ForthTalk to be of any use. Unfortunately ForthTalk does not appear to work with the Level 3 "Developer's version" of MacFORTH; working only with Level 2. Support is planned for CSI's new MacFORTH PLUS kernel.

Getting ForthTalk up and running is very simple. The author, Steve Lindner, apparently decided that MacFORTH's default limit of 500 tokens per program was not enough, so he provided a utility that allows MacFORTH programmers to use more tokens, the recommended number being 2000. This application is executed first to make room for the extensions, leaving some for user-written programs.

The ForthTalk Loader is then executed. This interesting piece of code is essentially a customized version of CSI's vocabulary librarian, which is included with the Level 2 MacFORTH system. Written by Ward McFarland, the FORTH code grabs the precompiled extensions from a couple of resources in the resource fork, neatly sidestepping the issue of how to distribute ForthTalk without distributing either the MacFORTH kernel or the source code to ForthTalk, which might prove damaging to InSite Computing. The ForthTalk Loader, having read in the extensions and attached them to the MacFORTH kernel, snapshots the kernel so that the extensions are a permanent addition to the kernel. The system then returns to the Finder.

That's all it takes to make a ForthTalk system. The remaining magic lies in the "Vanilla" file.

Vanilla contains the definitions of several useful flavors. The most obvious of these is Vanilla itself, the root flavor. Every other flavor is a subflavor of Vanilla. (Almost every other flavor. The exceptions are called mixins, and I'll get to them in a minute).

You're probably wondering "If this is the root flavor, why doesn't it get snapshotted into the kernel along with the flavor defining words?" The reason why is one of the few shortcomings of an otherwise fine system. In the current version of ForthTalk, flavors cannot be correctly snapshotted because they, or more accurately, their instances, exist as entities in the application heap, not in the FORTH dictionary. Furthermore, in many cases, the instance may point to an instance of another flavor, etc. Ultimately a snapshot utility will be written to deal with these unique requirements.

Having created the ForthTalk kernel, how is it used? The easiest thing to do first is simply double-click on the "Vanilla" file from the Finder. This will launch the ForthTalk kernel, load the "FORTH Blocks" file, and in turn the editor, and ultimately the "Vanilla" file.

You are now in a powerful object-oriented FORTH environment. The best thing to do now is to read Chapter One of the documentation. It is a simple, fun tutorial which, although simple in nature and objectives, covers everything from defining new flavors and methods to the important concept which sets this system apart from all others I have used: multiple inheritance.

A really basic data structure is always nice. So let's define an array, like this:

   FLAVOR Array Vanilla | 

Note: in ForthTalk, uppercase and lowercase are distinct. Make sure you case things consistently. In general, ForthTalk uses the convention that all uppercase words are "built-in" to the system, whereas mixed-case words were defined outside the kernel.

What have we done with the above line? We have created a new flavor called Array. It has Vanilla as a superflavor. The vertical line indicates that we are done defining the new flavor. Experience OOPS users are probably scratching their heads, wondering why you must explicitly tell the compiler when you are finished defining a new flavor. The answer is that with multiple inheritance, you can have more than one superflavor.

We've now defined a flavor called Array. What does it do? Nothing at this point. We need to tell it what kind of data structures and what kind of code make up an Array.

The tutorial opts to keep things simple and use a fixed-length array. In order not to distract from our discussion of object-oriented programming, I will do the same.

Let's make arrays to be big enough to contain ten longword (32-bit) values. We'll also need a way to keep track of how many of those ten elements are occupied.

Most OOPS call the data structures within their classes (or flavors, in ForthTalk) "instance variables" because they are unique for all instances of that class. ForthTalk is really no different, but it is different from most OOPS in not using instances of other flavors as instance variables. Instead it relies on "INST.XXXX" words ("INST.LONG," "INST.WORD," and "INST.SPACE") to create instance variables. So we can give Array its data structures like this:

    INST.LONG Array Count
    40 INST.SPACE Array Space

We have just allocated a total of 44 bytes (40 bytes plus a longword) to Array. 4 bytes can be referred to as "Count" in the methods that we write for arrays, and the remaining 40 are referred to as "Space."

Believe it or not, we have now given the flavor "Array" enough to work with in order to create arrays! We can create an object whose flavor is "Array" like this:

     Array CONSTANT MyArray

As you can see from this example, flavors are fairly intelligent FORTH words. When you execute a flavor, it figures out the total amount of space that it must allocate (44 bytes in Array's case), and allocates a block of that size in the heap. NOTE: flavors return a HANDLE to their data!

Since flavors return a handle, we can simply use the normal FORTH word CONSTANT to assign a name to the handle.

We now have a new flavor that we've created, and we've used it to create an instance of itself, which we've named MyArray. What can we do with MyArray?

At this moment MyArray is doing nothing but taking up space. What we need are methods for operating on the data in MyArray, and on any other arrays that we create.

One obvious thing to do would be to store things in our array. We want to create a method to do this, so let's call ours :Set. In ForthTalk, all methods begin with a colon (":"), which the documentation says is a convention used by Smalltalk. I beg to differ with the documentation on this point; in Smalltalk, methods end with a colon. For the sake of internal consistency I have chosen to use the ForthTalk convention.

The definition of :Set looks like this:

     METHOD Array :Set ( x n ---)
        4* Space + ! ;M

This method takes two operands on the stack. The value to store is first, and the element within the array is on the top of the stack.

The method first multiplies the array index by four since each entry is four bytes long. It adds the result to Space (which refers to the first byte of the array). The result is the address where we wish to store our value, and the normal FORTH word ! does the job.

Methods, like the instance variables that they manipulate, are buried somewhere within the flavor for which they are defined. Since that is the case, we need a way to make it possible to access them. This is done with the word DEFMESSAGE. It is used like this:

     DEFMESSAGE :Set

This adds the word :Set to the FORTH vocabulary. Whenever this word is executed, it will look in the superflavor chain for the object whose address is on the top of the stack for a method called ":Set". If it finds one, it will execute it, otherwise it will print an error message.

This raises two of the negative issues regarding ForthTalk. One is that messages must be defined externally with DEFMESSAGE before they may be used. This problem is not present in any other OOPS that I know of including Neon. The other is that with multiple inheritance, there is a definite performance impact on method lookups. Both these issues are expected to be addressed in a future release of ForthTalk, probably the one that runs under the new MacFORTH PLUS kernel.

We can use :Set to give values to our array, like this:

     3 0 MyArray :Set

This will assign the value of three to the zeroeth element of MyArray.

And here we see the beauty of object-oriented programming. The Array flavor is totally modular: its data cannot be accessed by anything other than its methods, and its methods cannot be accessed without following protocol, and are entirely self-contained, too! As long as we avoid code that is dependent upon Arrays having ten elements and avoid changing the interface to any of the methods, we are safe! (In reality we would probably make the Array flavor dynamically sized). We can write new methods for Array and fiddle around with its data structures without fear of the impact on any other part of the program! You can see why OOPS are becoming so popular for large programming projects or projects where a large team of programmers must work together!

:Init Method

In order for ForthTalk to be truly useful, there is one more concept that should be addressed: the :Init method.

:Init methods are usually needed, if only to provide some default values/actions for the instance of the flavor in question. In the case of Array, it would be nice to initialize the array to some set of values. For that reason, we have:

METHOD Array :Init ( mn   m2 m1 n --- instance)
   Count !
   Count @ 0 DO I SELF :Set LOOP
   SELF ;M

This method takes several values on the stack: first, a series of values to be assigned to the array elements, then the number of items there are to assign. The method first stores the number of elements in Count, and it then uses Count in a DO LOOP construct.

The loop counts from 0 to Count - 1 and :Sets the elements of its SELF to the values on the stack. For example:

5 4 3 2 1 5 MyArray :Init

This raises another interesting point about OOPS: they allow the programmer to write methods that use methods from either the same flavor or from one of the superflavors to get the job done. In this case, :Init uses :Set (since we want :Init to SET the elements to the values on the stack).

Like Smalltalk, ForthTalk allows the use of the pseudo-object SELF to refer to whatever object is currently executing a method.

Isn't this fun? We can add more methods now. One thing that's useful with Arrays is the ability to perform some function on all of the values stored in them. We'll call this method :DoToAll and take advantage of a fact of MacFORTH: we can execute any word by getting its token and saying EXECUTE. TOKEN.FOR is a MacFORTH word that returns the token value for a word.

With that thought in mind, here's :DoToAll:

METHOD Array :DoToAll LOCALS| token |
   Count @ 0 DO I 4* Space + token
   EXECUTE LOOP ;M

Note that this method passes the address of the value to the token, not the value itself. Whatever word token is for needs to be "aware" of that fact.

Also note that the MacFORTH local variable facility works just fine within methods. This makes it easier to define what goes into methods and what processing the methods do.

Before we forget, we'd better:

     DEFMESSAGE :DoToAll

We can do useful things with :DoToAll. One of them is to show the contents of the entire array. We can define:

METHOD Array :Print
   TOKEN.FOR ? SELF :DoToAll ;M

DEFMESSAGE :Print

With :DoToAll the definition of :Print becomes trivial. We can get the token value for ?, which is a standard FORTH word which gets the longword at the address on the stack and displays it using . (another standard FORTH word). Passing this token, along with SELF, to :DoToAll prints the values of each defined element. What could be simpler?

It's hoped that this somewhat drawn-out description of ForthTalk's capabilities is giving you some insights (no pun intended) into how this OOPS can make your life as a Macintosh programmer easier.

The remainder of the tutorial chapter in the ForthTalk documentation continues to develop the ideas behind the Array flavor. Ultimately a subflavor of Array called ObjectArray is created. The point behind ObjectArray is that its elements hold not just arbitrary numerical values but handles to instances of other objects.

This leads to some interesting concepts, such as creating a normal FORTH colon definition that passes a message to whatever object is on the top of the stack (assuming that the object "knows" the message). Again, the example given uses :Print (since so many kinds of objects can respond in a meaningful way to a :Print message). So, you wind up with something like this:

: Print  @ DUP INSTANCE? IF :Print ELSE CR . THEN ;

This word is almost ridiculously simple: given an address on the stack, it uses the word INSTANCE? to determine whether the address contains a handle to an object or not. If it does, the word assumes that the object understands the message :Print and uses it, otherwise the word simply prints the number, after printing a carriage return.

In conjunction with the ObjectArray mentioned above, this opens up a rather exciting possibility: printing an ObjectArray by passing the :Print message to all of its elements. Like any robust OOPS, ForthTalk has inheritance, which means that ObjectArrays inherit the :DoToAll method from their superflavor (Arrays). Since that is the case, defining the :Print method for ObjectArrays becomes very simple. It looks like this:

METHOD ObjectArray :Print
   TOKEN.FOR Print SELF :DoToAll ;M
AXE Print

Note: the AXE is to remove the header for our Print word, since it exists only as a tool to be used within the :Print method for ObjectArrays.

This simple method uses our smart word Print to send the :Print message to all of the objects in the ObjectArray. As long as the object is of a flavor that understands :Print the ObjectArray flavor will exhibit sensible behavior, otherwise Print will just print the value stored in the ObjectArray. If that happens, you know that you have a bug.

The upshot of all of this is that with just a couple of flavors and a few methods, you have the capability to create pictures. In an OOPS, a picture can simply be an ObjectArray which contains graphics objects that understand the :Print message. As long as all of the objects understand :Print asking the ObjectArray to :Print itself will result in each object :Printing itself, with the total result being a picture at some point on the screen.

At this point the tutorial becomes interesting. Here is some sample code. See if you can determine in what direction we're moving with it:

FLAVOR Circle Vanilla |
   INST.WORD Circle X
   INST.WORD Circle Y
   INST.WORD Circle Radius

METHOD Circle :Init ( X Y Radius --- SELF)
   Radius W!
   Y W!
   X W! SELF ;M

METHOD Circle :Print ( --- )
   X W@ Y W@ Radius W@ FRAME CIRCLE ;M

     FLAVOR Line Vanilla |
        INST.WORD Line X1
        INST.WORD Line Y1
        INST.WORD Line X2
        INST.WORD Line Y2

METHOD Line :Init ( X1 Y1 X2 Y2 --- SELF)
   Y2 W!
   X2 W!
   Y1 W!
   X1 W! SELF ;M

METHOD Line :Print ( --- )
   X1 W@ Y1 W@ MOVE.TO
   X2 W@ Y2 W@ DRAW.TO ;M

Some ideas are probably glimmering by now. There's no point in reproducing the ForthTalk tutorial here in its entirety. Instead, I will leave the reader with a few questions to get him/her going.

What happens if you rewrite the graphics methods so they do their drawing relative to where the pen is, rather than drawing at absolute locations?

What we are shooting for is a flavor that, when instantiated, creates an object that, when sent a :Print message, prints itself wherever we told it to at the time of instantiation.

The Whole Point

If we can do that: make a flavor which contains instance variables X and Y, and a FLAV.LONG referring to an ObjectArray which in turn contains :Printable objects that print relative to the current pen position (whew! This is getting deep), THEN we can perform small miracles. Why? Because thanks to the magic of multiple inheritance, we can animate these objects - and we can do so in such a way that the animation code can immediately be used for other flavors of objects.

This is what this whole article has been leading up to. We are going to create a new flavor called simply Animation. We are assuming that we have this relative-drawing flavor (the example in the documentation defines the flavor Automobile, which uses the ObjectArray defined earlier to draw a stick-figure car relative to the current pen position).

I said that flavor Animation would be general, and it will: it will allow animation of any object that understands the :Print message (so far all of ours do), and the :GetXYAddr message (which so far NONE of ours do). Adding the ability to get the addresses of X and Y from any flavor that has them, like Automobile, is trivial:

DEFMESSAGE :GetXYAddr
METHOD Automobile :GetXYAddr
   X Y ;M

As you may have noticed, one way that the tutorial has been making methods general is by providing them with some external word (such as Print) which sends messages to do the dirty work. Vectoring is also very big (and what is an ObjectArray but a means of sending the same message to a bunch of different objects)? We'll take advantage of an external word again with Animation, but first let's create this fascinating flavor:

FLAVOR Animation |
   INST.WORD Animation MoveToWhere
DEFMESSAGE :Animate
DEFMESSAGE :SetAnimation

The most obvious weird thing about Animation so far is that it does not have Vanilla as a superflavor. This fact makes Animation what is known as a mixin; it is intended to be a superflavor itself, since by itself it has virtually no functionality.

It does understand two messages, though: :Animate and :SetAnimation. Let's see :Animate first, since it's the one that actually moves the Automobile:

METHOD Animation :Animate ( --- )
   SELF :GetXYAddr LOCALS| Y X |
   SELF :Print
   BEGIN
      SELF :Print
      X Y MoveToWhere W@EXECUTE
      ( must leave a flag)
      SELF :Print
   UNTIL ;M

It seems easy - as it should. This method assumes basically two things: that the current pen mode is PATXOR, so that successive drawing operations of the same thing at the same place will alternate the appearance and disappearance of the object, and that MoveToWhere contains the token of a word which takes the addresses of the X and Y location of the object and returns a boolean indicating whether the animation is done (true) or not (false).

That only leaves :SetAnimation, which is easy to define:

METHOD Animation :SetAnimation ( token ---)
( token arglist is { X Y --- flag} where
  X = address of picture's X coordinate
  Y = address of picture's Y coordinate
  flag = TRUE if animation loop should end,
           FALSE to continue)
   MoveToWhere W! ;M

It's all comment except for the last line, which simply stores the token.

Now we can define an animated Automobile. We'll call it flavor MovingAuto, like this:

FLAVOR MovingAuto Automobile Animation |

That's all that's needed to create an animated automobile, aside from creating an instance! To do that, we can just say:

10 100 MovingAuto :Init CONSTANT CarToon

Well, almost all! We still have to create the word that actually changes X and Y and returns a true or false flag, depending upon whether we are done or not:

: MoveRight ( X\Y --- flag)
   DROP DUP W@ 8+ OVER W! W@ 400 > ;
TOKEN.FOR MoveRight CarToon :SetAnimation

This simple word ignores the address of Y completely (DROP). It then adds eight to the value of X (move the picture eight pixels to the right). Finally, the word checks the value of X to see if it has gone higher than 400.

The last line simply uses the :SetAnimation method to store the token for our animation word so that we can move our car. So to see the CarToon move to the right on the screen, just say:

        CarToon :Animate

and watch it drive by!

With a new flavor containing only two methods and a helpful FORTH word, we have animated an otherwise inanimate object (pun intended).

I'll close with a couple of paragraphs from the ForthTalk manual:

"(A) useful idea would be to keep around a palette of motions and motion combinations. These would include things like Bounce, Stop, GoToZero, Orbit, ParabolicArc, etc. These could be interchangeably used for any of your other pictures."

"For another idea to try, :GetXYAddr could return the addresses of *any* two parameters, like Radius and Color, or like Speed and ZoomFactor. Then the Animation flavor would vary these things instead of just screen position."

Final comment: if MacFORTH is your bag, and you want object-oriented programming and want it to be intuitive to an old FORTH hacker, but you want it to be very powerful and easy to learn, then spend the $55 and get ForthTalk. You won't regret it.

MacFORTH users will ultimately be able to get MacFORTH PLUS and the version of ForthTalk that runs with it.

In the meantime, there are a growing number of people who have more or less permanently moved over to MACH 2, the excellent 83 standard FORTH development system from Palo Alto Shipping. I am in the process of trying to convince InSite Computing to port their outstanding effort over to the MACH 2 environment. Palo Alto Shipping has expressed an interest, Steve Lindner has expressed his personal interest, and I'd be interested, both as a MACH 2 user and as (hopefully) the MACH 2 version implementor. I'll keep you posted on any progress made in that area.

ForthTalk is available from:

InSite Computing
Box 2949
Ann Arbor, MI  48106
(313) 994-3660
 

Community Search:
MacTech Search:

Software Updates via MacUpdate

Google Chrome 75.0.3770.142 - Modern and...
Google Chrome is a Web browser by Google, created to be a modern platform for Web pages and applications. It utilizes very fast loading of Web pages and has a V8 engine, which is a custom built... Read more
Notability 4.0.4 - Note-taking and annot...
Notability is a powerful note-taker to annotate documents, sketch ideas, record lectures, take notes and more. It combines, typing, handwriting, audio recording, and photos so you can create notes... Read more
ffWorks 1.3.1 - Convert multimedia files...
ffWorks, focused on simplicity, brings a fresh approach to the use of FFmpeg, allowing you to create ultra-high-quality movies without the need to write a single line of code on the command-line.... Read more
EtreCheck Pro 6.0.2 - For troubleshootin...
EtreCheck is an app that displays the important details of your system configuration and allow you to copy that information to the Clipboard. It is meant to be used with Apple Support Communities to... Read more
Adobe Premiere Pro CC 2019 13.1.3 - Digi...
Premiere Pro CC 2019 is available as part of Adobe Creative Cloud for as little as $52.99/month. The price on display is a price for annual by-monthly plan for Adobe Premiere Pro only Adobe Premiere... Read more
BitTorrent 7.4.3 - Official client of th...
BitTorrent is a protocol for distributing files. It identifies content by URL and is designed to integrate seamlessly with the web. Its advantage over plain HTTP is that when multiple downloads of... Read more
BetterTouchTool 3.134 - Customize multi-...
BetterTouchTool adds many new, fully customizable gestures to the Magic Mouse, Multi-Touch MacBook trackpad, and Magic Trackpad. These gestures are customizable: Magic Mouse: Pinch in / out (zoom)... Read more
EtreCheck Pro 6.0.2 - For troubleshootin...
EtreCheck is an app that displays the important details of your system configuration and allow you to copy that information to the Clipboard. It is meant to be used with Apple Support Communities to... Read more
BitTorrent 7.4.3 - Official client of th...
BitTorrent is a protocol for distributing files. It identifies content by URL and is designed to integrate seamlessly with the web. Its advantage over plain HTTP is that when multiple downloads of... Read more
Adobe Premiere Pro CC 2019 13.1.3 - Digi...
Premiere Pro CC 2019 is available as part of Adobe Creative Cloud for as little as $52.99/month. The price on display is a price for annual by-monthly plan for Adobe Premiere Pro only Adobe Premiere... Read more

Latest Forum Discussions

See All

TEPPEN guide - Tips and tricks for new p...
TEPPEN is a wild game that nobody asked for, but I’m sure glad it exists. Who would’ve thought that a CCG featuring Capcom characters could be so cool and weird? In case you’re not completely sure what TEPPEN is, make sure to check out our review... | Read more »
Dr. Mario World guide - Other games that...
We now live in a post-Dr. Mario World world, and I gotta say, things don’t feel too different. Nintendo continues to squirt out bad games on phones, causing all but the most stalwart fans of mobile games to question why they even bother... | Read more »
Strategy RPG Brown Dust introduces its b...
Epic turn-based RPG Brown Dust is set to turn 500 days old next week, and to celebrate, Neowiz has just unveiled its biggest and most exciting update yet, offering a host of new rewards, increased gacha rates, and a brand new feature that will... | Read more »
Dr. Mario World is yet another disappoin...
As soon as I booted up Dr. Mario World, I knew I wasn’t going to have fun with it. Nintendo’s record on phones thus far has been pretty spotty, with things trending downward as of late. [Read more] | Read more »
Retro Space Shooter P.3 is now available...
Shoot-em-ups tend to be a dime a dozen on the App Store, but every so often you come across one gem that aims to shake up the genre in a unique way. Developer Devjgame’s P.3 is the latest game seeking to do so this, working as a love letter to the... | Read more »
Void Tyrant guide - Guildins guide
I’ve still been putting a lot of time into Void Tyrant since it officially released last week, and it’s surprising how much stuff there is to uncover in such a simple-looking game. Just toray, I finished spending my Guildins on all available... | Read more »
Tactical RPG Brown Dust celebrates the s...
Neowiz is set to celebrate the summer by launching a 2-month long festival in its smash-hit RPG Brown Dust. The event kicks off today, and it’s divided into 4 parts, each of which will last two weeks. Brown Dust is all about collecting, upgrading,... | Read more »
Flappy Royale is an incredibly clever ta...
I spent the better part of my weekend playing Flappy Royale. I didn’t necessarily want to. I just felt like I had to. It’s a hypnotic experience that’s way too easy to just keep playing. | Read more »
Void Tyrant guide - General tips and tri...
Void Tyrant is a card-based dungeon-crawler that doesn’t fit in the mold of other games in the genre. Between the Blackjack-style combat and strange gear system alone, you’re left to your own devices to figure out how best to use everything to your... | Read more »
Webzen’s latest RPG First Hero is offici...
You might be busy sending your hulking Dark Knight into the midst of battle in Webzen’s other recent release: the long-anticipated MU Origin 2. But for something a little different, the South Korean publisher has launched First Hero. Released today... | Read more »

Price Scanner via MacPrices.net

Price drop! Clearance 12″ 1.2GHz Silver MacBo...
Amazon has dropped their price on the recently-discontinued 12″ 1.2GHz Silver MacBook to $849.99 shipped. That’s $450 off Apple’s original MSRP for this model, and it’s the cheapest price available... Read more
Apple’s 21″ 3.0GHz 4K iMac drops to only $936...
Abt Electronics has dropped their price on clearance, previous-generation 21″ 3.0GHz 4K iMacs to only $936 shipped. That’s $363 off Apple’s original MSRP, and it’s the cheapest price we’ve seen so... Read more
Amazon’s Prime Day savings on Apple 11″ iPad...
Amazon has new 2018 Apple 11″ iPad Pros in stock today and on sale for up to $250 off Apple’s MSRP as part of their Prime Day sale (but Prime membership is NOT required for these savings). These are... Read more
Prime Day Apple iPhone deal: $100 off all iPh...
Boost Mobile is offering Apple’s new 2018 iPhone Xr, iPhone Xs, and Xs Max for $100 off MSRP. Their discount reduces the cost of an Xs to $899 for the 64GB models and $999 for the 64GB Xs Max. Price... Read more
Clearance 13″ 2.3GHz Dual-Core MacBook Pros a...
Focus Camera has clearance 2017 13″ 2.3GHz/128GB non-Touch Bar Dual-Core MacBook Pros on sale for $169 off Apple’s original MSRP. Shipping is free. Focus charges sales tax for NY & NJ residents... Read more
Amazon Prime Day deal: 9.7″ Apple iPads for $...
Amazon is offering new 9.7″ WiFi iPads with Apple Pencil support for $80-$100 off MSRP as part of their Prime Day sale, starting at only $249. These are the same iPads found in Apple’s retail and... Read more
Amazon Prime Day deal: 10% (up to $20) off Ap...
Amazon is offering discounts on new 2019 Apple AirPods ranging up to $20 (10%) off MSRP as part of their Prime Day sales. Shipping is free: – AirPods with Charging Case: $144.99 $15 off MSRP –... Read more
Amazon Prime Day deal: $50-$80 off Apple Watc...
Amazon has Apple Watch Series 4 and Series 3 models on sale for $50-$80 off Apple’s MSRP as part of their Prime Day deals with prices starting at only $199. Choose Amazon as the seller rather than a... Read more
Amazon Prime Day deal: 50% discount on Apple...
Amazon has Apple Smart Keyboards for current-generation 10″ iPad Airs and previous-generation 10″ iPad Pros on sale today for $79.50 shipped as part of their early Prime Day deals. That’s a 50%... Read more
Abt drops prices on clearance 2018 MacBook Ai...
Abt Electronics has dropped prices on clearance 2018 13″ MacBook Airs by $201 with models now available starting at only $998. Shipping is free: – 13″ 1.6GHz/128GB MacBook Air (Space Gray, Silver, or... Read more

Jobs Board

*Apple* Graders/Inspectors (Seasonal/Hourly/...
…requirements. #COVAentryleveljobs ## Minimum Qualifications Some knowledge of agricultural and/or the apple industry is helpful as well as the ability to comprehend, Read more
Best Buy *Apple* Computing Master - Best Bu...
**710003BR** **Job Title:** Best Buy Apple Computing Master **Job Category:** Store Associates **Location Number:** 000171-Winchester Road-Store **Job Description:** Read more
Best Buy *Apple* Computing Master - Best Bu...
**709786BR** **Job Title:** Best Buy Apple Computing Master **Job Category:** Sales **Location Number:** 000430-Orange Park-Store **Job Description:** **What does a Read more
Geek Squad *Apple* Master Consultation Agen...
**709918BR** **Job Title:** Geek Squad Apple Master Consultation Agent **Job Category:** Services/Installation/Repair **Location Number:** 000106-Palmdale-Store Read more
*Apple* Systems Architect/Engineer, Vice Pre...
…its vision to be the world's most trusted financial group. **Summary:** Apple Systems Architect/Engineer with strong knowledge of products and services related to Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.