Scala リストに要素を追加する &その時の注意事項

ScalaのSeq型の一つである、List型の宣言は下記のようにします。

var ages = List(42, 61, 29, 64)

リストの末尾に要素を追加する場合には、次のようにします。

ages :+ 10

で、この時の注意なんですが、いかにも ages ってリストに 10 という要素が足されたようになってますが、そうではありません。

object Main extends App {
  var ages = List(42, 61, 29, 64)
  println(s"The oldest person is ${ages.max}")

  ages :+ 10
  println(s"The youngest person is ${ages.min}")

}

上記の出力は次のようになります。

The oldest person is 64
The youngest person is 29

ほげえええ

ages :+ 10 とやったときに、なんと新しいSeqが生まれていて、そこに追加されているのです。元のagesに追加されているわけではないのです。

下記のように変更してみます。

object Main extends App {
  var ages = List(42, 61, 29, 64)
  println(s"The oldest person is ${ages.max}")

  var new_ages = ages :+ 10
  println(s"The youngest person is ${new_ages.min}")

}

出力は次のようになります。

The oldest person is 64
The youngest person is 10

あー、よかった、できたできた。(๑>◡<๑)

Scala IntelliJ sbtでビルドするプロジェクトをインポートする

前回、下記の投稿で新しくプロジェクトを作る場合に、sbtでビルドしたい場合のプロジェクトは作るときに気を付けないといけないよ、という話を書きましたが

既存のプロジェクトをIntelliJで動作させたい場合も気を付けるべきポイントがあるので、書いておきます。

環境は、Windows10 + IntelliJ コミュニティバージョン 2020.1 です。

最初の画面で、「Open or Import」をクリックします。

開いたダイアログでうっかりプロジェクトの入っているフォルダを選んでしまいそうですが、それはダメです。

上記のように、build.sbt ファイルを選んで、

OKをクリックしてください。

そうすると、sbtでビルドするプロジェクトだと認識してくれます。o(>▽<)o

これで、sbt tool windowも、sbt shellウィンドウも見れるようになりました!

Scala ScalatraをIntelliJを使って開発&デバッグする Windows10

さてさて、前々回前回とsbtのScalaプロジェクトをIntelliJで開発するためにてこずっていたワタクシですが、やっと真打ち登場!です。

もともとやりたかったことは、Scalatraで作られたプロジェクトをIntelliJでデバッグとかしながらオシャレに開発していきたかったのです。

ScalatraはScalaのフレームワークです。今回は、バージョン2.6.5です。

環境は、Windows10 + IntelliJ コミュニティバージョン2020.1 です。

Scala IntelliJ sbtでビルドするプロジェクトをインポートする

で説明したように、プロジェクトをインポートします。

この後、sbt tool windowとかsbt shellのウィンドウがなければ、sbtでビルドすいるプロジェクトだと認識されていませんので、やりなおしましょう…。

Buildに失敗したというメッセージが出ます。

Extracting structure failed
(Global / dumpStructureTo) java.io.FileNotFoundException: C:\Users

気にしたほうがいいのかもしれませんが、支障は今のところないので、気にせず続行します。

デフォルトではsbtでビルドできるようになってないので、下記でも紹介しているように、

File→Setting→Build, Excution…→Build Tools→sbtの画面で

Use sbt shellとあるところのチェックボックスを二つチェックします。

sbt shellのウィンドウで、

jetty:start

と打ち込みます。いろいろ、バーっと表示が出ますが、

2020-07-31 16:55:08.612:INFO:oejs.Server:main: Started @2375ms

と出て、Jetty Webサーバーがちゃんと動作したっぽいです!!
ブラウザなどで localhost:8080 に接続すると、ちゃんと応答が帰ってきます。やったぁ。

さて、次の課題はデバッグです。

デフォルトでは、デバッグの緑の虫アイコンさえ、灰色になってます。

虫さん…死んでる…。

このままではデバッグできませんので、下記を見てやります。

https://scalatra.org/getting-started/ide-support.html

上記と同じ内容ですが、解説も加えて下記に書いておきます。

Run → Edit configurations 

として、Remoteというのを選んで

Attach to remote JVM

というのが選択されているのを確認して、OKをクリックします。

ちなみに、ここでJVMに下記のオプションをつけて実行することになっています。
-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005

おまじないみたいですが、この内容が知りたければ、下記サイトに書いてあります。

https://docs.oracle.com/javase/1.5.0/docs/guide/jpda/conninv.html

虫のアイコンが緑に光り輝きますが、まだここでは押さないでください。


build.sbt に次のオプションを足します。

javaOptions ++= Seq(
"-Xdebug",
"-Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005"
}


これで、もう一度ビルドします。jetty:start ってやって、緑の虫さんのデバッグアイコンをクリックします。

注意事項ですが、 jetty:start ってやって から、デバッグしないとできません。

5005番のポートを使う、JVMのプロセスにアタッチしてデバッグするからからなので、JVMが立ち上がってないとデバッグできないのです。

Debug ウィンドウに

Connected to the target VM, address: 'localhost:5005', transport: 'socket

って表示されたら、とりあえずデバッグが接続できています。

localhost:8080 にWebブラウザで接続してみます。

すると、設定してあったブレークポイントで止まりました!やったね⊂(^-^)⊃


Scala IntelliJ IDEAでsbtのプロジェクトを作る Windows10

現在私は、ScalaのScalatraというフレームワークで書かれた開発プロジェクトをわけあって引き継いでおります。
前に作っていた人は、現在うちの会社で別の仕事をしているのですが、その人は開発環境とかあんまり気にしないタイプで、テキストエディタ的にVisual Studio Codeを使っていたということです。

ただ、私は開発環境でデバッグとかしながら開発したい派です。Android Studioとかも使っていて親しみがあるので、IntelliJ IDEAでやってやろうと思いました。

しかし、いきなりIntelliJにScalatraのコードをブチこんでも全然うまくいかなかったんですよ。Scalatraのバージョンは2.6.5です。

というわけで、まずは初心にかえり、超簡単なプロジェクトをIntelliJで作ってみます。

環境は、Windows10 + IntelliJ IDEAコミュニティバージョン2020.1です。

ここで、とっても大事な話をします。

sbtで動かすScalaプロジェクトと、sbtを使わないScalaプロジェクトは、IntelliJに最初の導入をする部分で違います。

ここ間違うと、私みたいにはまります。(ノω・、) ウゥ・・・

最初、下記のページを見てやってたんですよ。

Intellij で sbt を使って Scala プロジェクトをビルドする
https://docs.scala-lang.org/ja/getting-started/intellij-track/building-a-scala-project-with-intellij-and-sbt.html

File→New→Projectと行くと、下記のような画面になりますが、

↑ここでScalaを選択してはダメです。

↓下記のように、左がScalaで、右がsbtを選択しましょう。


今回は、サンプルなので、気を付ける場所はここだけです。

Nextを押して、プロジェクトの保存場所を選択して、OKをクリックします。

プロジェクトを作ると、sbtの構成を、IntelliJが作ってくれるので、多少時間がかかります。

サンプルとして、さっきも紹介した下記のサイトにあるサンプルコードを書いておきます。

https://docs.scala-lang.org/ja/getting-started/intellij-track/building-a-scala-project-with-intellij-and-sbt.html

object Main extends App {
    val ages = Seq(42, 75, 29, 64)
    println(s"The oldest person is ${ages.max}")
}

画面の一番下に、sbt shellというタブがあります。

これで、

「ん~ 動くのかな?」

ということで、run と打ち込んでも、何も起こりません。

「動け、動け、動け、動いてよ~!!」

と泣き叫びたくなりますが、落ち着きましょう(´ω`)。

File→Setting→Build, Excution…→Build Tools→sbtの画面で

Use sbt shellとあるところのチェックボックスを二つチェックします。

OKをクリックして、sbt shellのところでもう一度、run って入力します。

すると、ちゃんと動作して、プログラムの実行結果がsbt shellに表示されました!

The oldest person is 75

ってやつが実行結果ですね。


Vue.js コンポーネントの中のテンプレートで配列のオブジェクトのリンクを表示する

以前、Vue.jsを使って、下記のようなことをしましたが、「早いもんだぜ」でもう1年が経ちました。

私ってめちゃくちゃ忘れっぽいんですよ。健康だってことですかね?つまり、Vueのことについてカケラも覚えていませんでした…。

特に時間がかかったのが、
「リンクを作る」
ところです。

「エッツ そんなのちょちょいとできないの?」

と思われると思いますが、できなかったんですよ。

前置き長いですが、本題に入ります。ちなみに、この度のケースでは、Nuxtとかで使っているわけではなく、Vueをパーツで使っています。Routerとかを使うわけではありません。

今回はVue.jsでリンク、つまり<a>タグの”href”属性を作ることをやります。

下記は、まだリンクがありません。

<!DOCTYPE html>
<html lang="ja">

<head>
    <meta charset="UTF-8">
    <script src="https://unpkg.com/vue@2.5.17"></script>
</head>

<body>

<div id="fruits-component">
  <ol>
    <fruits-component v-for="eachFruit in fruitsItems" :key="eachFruit.name" :fantastic-fruit="eachFruit">     	
    </fruits-component>
  </ol>
</div>

<script>

let fruitsItems= [
    {name:'りんご', id:'101'}, {name:'バナナ',id:'102'}, {name:'なし',id:'103'}
  ];


let fruitsComponent = Vue.component('fruitsComponent',{
		props: {
			  'fantasticFruit': { 
			      type: Object, 
			      required: true 
			    }
			  },

		template: ' <li>{{fantasticFruit.name}}</li>',
});

new Vue({
	
  el: '#fruits-component',
  data: { fruitsItems  },
  components: {
	    'fruitsComponent': fruitsComponent,
	  }
  
})

</script>
</body>

上記の解説です。

①データは [{name:’りんご’, id:’101′}, {name:’バナナ’,id:’102′}, {name:’なし’,id:’103′}] となっています。3つのオブジェクトが一つの配列に入っています。

②コンポーネントという仕組みを使っています。
HTMLタグでは<fruits-component> </fruits-component>で表現されるところがコンポーネントの中身になります。
わかりにくい部分なんですが

<fruits-component v-for="eachFruit in fruitsItems" :key="eachFruit.name" :fantastic-fruit="eachFruit">         
</fruits-component>

ってなっている、:fantastic-fruit=”eachFruit” が、v-forで回しているeachFruitを fruits-component コンポーネントのfantastic-fruitに結びつけています。データバインディングのディレクティブというやつです。
:fantastic-fruit

v-bind:fantastic-fruit
の略です。詳しくは、本家サイトをご覧ください。

https://v1-jp.vuejs.org/guide/syntax.html

③ fruits-component コンポーネントのfantastic-fruitに結び付いたデータを、コンポーネント内のテンプレート構文で出力します。
template: ‘ {{fantasticFruit.name}}’ の部分ですね。

正直なところ、同じデータの参照を、いろいろな名前で呼んでいるので、わかりにく…って思います。(もっとスッキリするやり方があれば教えてください。)

さてさて、本題の<a>リンクの出力に行きます。

コンポーネントのテンプレート部分だけ変更します。

let fruitsComponent = Vue.component('fruitsComponent',{
		props: {
			  'fantasticFruit': { 
			      type: Object, 
			      required: true 
			    }
			  },

		template: '<li><a href="{{fantasticFruit.id}}.html">{{fantasticFruit.name}}</a></li>',
});

これで<a>リンクができたように見えますが、実はできてません。出力されたHTMLを見ると、下記のようになっています。

<a href="{{fantasticFruit.id}}.html">りんご</a>

ふぇぇ~なんで~(>_<)

となりますが、XSSを防ぐために、このようになっているようです。(すみません、Vue関連のどっかのサイトで見た気がするのですが、リファレンスがわからなくなってしまいました…。)

一つの手段は、computed という機能を使うことです。fruitsComponentの中身だけ、次のように書き換えます。

let fruitsComponent = Vue.component('fruitsComponent',{
		props: {
			  'fantasticFruit': { 
			      type: Object, 
			      required: true 
			    }
			  },

		template: '<li><a :href="fruitURL">{{fantasticFruit.name}}</a></li>',
		computed:    {
			  fruitURL: function () {
			      return this.fantasticFruit.id + ".html";
	    	  }
		}
});

:href=”fruitURL” とやっているところで、hrefという属性に、fruitURLを紐づけています。前述もしました、データバインディングです。

computedの中から、popsにあるデータにアクセスするときは

this.fantasticFruit.id

.html の部分が必要なければ単純に、テンプレートの中身を

template:'{{fantasticFruit.name}}',

としてもできます。が、この中にjavascriptの文字列が書けるようなので、+”html” とかで行けそうですが、何かと面倒そうだったのでやめました…。