tgoossens
tgoossens

Reputation: 9856

How to write this java code in clojure (tips)

The question

I'm learning clojure and I love learning languages by example. But I do not like it just get a complete answer without me having to think about it.

So what I want is just some tips on what functions I might need and maybe some other clues.

The answer that I will accept is the one that gave me the necessary building blocks to create this.

public class IntervalMap<K extends Comparable<K>, V> extends
TreeMap<K, V> {

V defaultValue = null;

public IntervalMap(V defaultValue) {
    super();
    this.defaultValue = defaultValue;
}

/**
*
* Get the value corresponding to the given key
*
* @param key
* @return The value corresponding to the largest key 'k' so that
*         &quot; k is the largest value while being smaller than 'key' &quot;
*/
public V getValue(K key) {

    // if it is equal to a key in the map, we can already return the
    // result
    if (containsKey(key))
        return super.get(key);

    // Find largest key 'k' so that
    // &quot; k is the largest value while being smaller than 'key' &quot;

    // highest key
    K k = lastKey();

    while (k.compareTo(key) != -1) {

        k = lowerKey(k);

        if (k == null)
            return defaultValue;
    }

    return super.get(k);

    }

    @Override
    public V get(Object key) {
        return getValue((K) key);
    }
}

Update I want to recreate the functionality of this class

For examples you can go here: Java Code Snippet: IntervalMap

Upvotes: 2

Views: 265

Answers (4)

sw1nn
sw1nn

Reputation: 7328

I'd be looking at some combination of:

  • (sorted-map & key-vals) - will allow you to create a map ordered by keys. you can supply your own comparator to define the order.

  • (contains? coll key) - tests whether a collection holds an item identified by the argument (this is a common source of confusion when applied to vector, where contains? returns true if there is an element at the given index rather than the given value)

  • (drop-while pred coll) lets you skip items in a collection while a predicate is true

Upvotes: 3

Beyamor
Beyamor

Reputation: 3378

A few things that I used in my implementation of an interval-get function:

  • contains?, like @sw1nn suggested, is perfect for checking whether a map contains a particular key.
  • keys can be used to get all of the keys in a map.
  • filter keeps all of the elements in a sequence meeting some predicate.
  • sort, as you have have guessed, sorts a sequence.
  • last returns the last element in a sequence or nil if the sequence is empty.
  • if-let can be used to bind and act on a value if it is not falsey.

The usage of the resulting function was as follows:

(def m {0 "interval 1", 5 "interval 2"})

(interval-get m 3) ; "interval 1"
(interval-get m 5) ; "interval 2"
(interval-get m -1) ; nil

Upvotes: 2

Ankur
Ankur

Reputation: 33657

If you want to implement the code block "conceptually" in clojure then the existing answers already answer your question, but in case you want the code block to be "structurally" same in clojure (i.e the subclassing etc) then have a look at gen-class and proxy in clojure documentation.

Upvotes: 0

Michiel Borkent
Michiel Borkent

Reputation: 34860

I would just use a map combined with a function to retrieve the closest value given a certain key. Read about maps and functions if you want to know more.

If you want to be able to mutate the data in the map, store the map in one of clojure's mutable storage facilities, for example an atom or ref. Read about mutable data if you want to know more.

You could use a function that has closed over the default value and/or the map or atom referring to a map. Read about closures if you want to know more.

The use of Protocols might come in handy here too. So, read about that too. Enough to get you going? ;-)

Upvotes: 2

Related Questions