So-net無料ブログ作成
検索選択
プログラミング ブログトップ
前の10件 | 次の10件

.bash_historyでRuby on Rails5インストール作業をプレイバック。 [プログラミング]

LXCにUbuntu16.04入れて、適当に一般ユーザー作る。そこから。


sudo apt install ruby
ruby -v


2.3とか結構新しいバージョンが入ってる。ver.2に入るころはかなり手を抜いていたのにね。面倒くさいからrbenvとか使わない。

gem -v


あ~rubygem一緒に入るっぽい。
これで一気にRailsが入ると思ったらどっこい。

sudo gem install rails

エラーが出た。

sudo apt install ruby-dev build-essential

まだ足りないらしくググって見る。nokogiriが悪いっぽいが。

sudo gem install nokogiri


コンパイルできないとか何とか

sudo apt install zlib1g-dev


Ubuntuのリポジトリサーバが死んでいるらしくファイルを取ってこれない。UbuntuのAPTサーバはたまに死んでいて、一日経つと復活していたりする。気長に待てないよなぁ。

仕方がないから他のものを入れる。

sudo apt install postgresql
sudo apt install elinks


elinksにおいてはずっと前に使ったっきりだから、Railsの動作確認に使えるかどうか良く分かってない。というか、まだRails入ってないから確かめようがない。

インストール作業ばっかりなんだから、わざわざ一般ユーザーでsudoする必要なかったなぁ。まぁ今度から環境設定のときは、コンテナのルートユーザーまんまで作業しよう。

あ~凡ミス。
sudo apt update && sudo apt upgrade

忘れてた。Ubuntuのメンテナさん疑ってごめんw。

すんなり通る。
sudo apt install zlib1g-dev


でもrailsは同じエラーを出していてもう一回build-essentialを入れたらコンパイルし始めた。なんでgcc入らんかったんやろ。

rails new hoge


上手くいくと思ったら、sudoの実行時にコケる。
sudo: no tty present and no askpass program specified

~/.bashrcに
alias sudo='sudo -S'
してあるから大丈夫だと思ったのに、他のスクリプト内だと有効じゃないみたい。なんか良く分からないな。LXCコンテナは色々と面倒。wettyだからnode.jsの設定でssh -tとか何とかしたほうが良さそうだ。
http://fishrimper.blogspot.jp/2012/09/ssh-sudo.html

shopt -s expand_aliases


やったけど上手くいかず。

http://qiita.com/narumi_/items/77002a12d62585da1fbe

やっぱり根本からやらんとあかんらしい。


でも問題となるところが違っていた。
まず、家に帰ってssh -t -t でつなぐようにWettyを設定してみたがダメでした。

/etc/sudoer に書いてみてもダメでした。
もしやと思い、家なので直でsshをつないでrails newを行っても
sudo: no tty present and no askpass program specified
が同じように出るので、sudoでrails newを動かしたらすんなり入って、前記のエラーが出なくなった。あんまりsudoで動かしたくないのだが仕方ない(メッセージで管理者権限で動かすなみたいなのが出てくるし)。


その後は、Sqlite関係のエラーが出るので、

sudo apt install sqlite3 libsqlite3-dev


あたりを入れたと思う。再度rails newで最後まで通る。
rails sで動かそうとするととexecjsあたりのエラーが出るので

sudo apt install nodejs


で解決。これで動くと思った。何か忘れている気もするが大体こんなもの。


LXCを抜けてホストOSに戻ってきたら、PostgreSQLが動いてた。ps axで普通に確認できた。コンテナでインストールされているものがデーモンとして動いてるのっていいのかな。ためしにコンテナを止めてみる。あ、Postgresも止まった。なんか良く分からないけど、コンテナで動いていてもホストOS側で見えるらしい。普通のプロセスは見えないのが普通だと思うけど、デーモンだからなのかもしれない。でも、なんか気持ち悪いな。コンテナでメモリ仕切っている意味ってあるのかな。

にしても、LXCコンテナの中でtmux使えないのな。どこかでUbuntu17.04を入れるとできるよ、みたいなことを書かれていた気がするが、debファイルででも入れられないものか。ちょっとしたところで、LXCで問題が出たりしていることも少なくないかも、気づいてないだけで。


タグ:Rails
コメント(0) 
共通テーマ:パソコン・インターネット

golangでwget -rで取りにくい画像を取りにいくものを作ったり [プログラミング]

wget -rでそのサイトを網羅的に引っこ抜く方法はほうぼうで出ていると思います。Windows10ではBash on Windowsですぐにwgetを叩けるようになっているので、サイトをもぎ取ってくるには楽チンな方法だったりします。実際、私もいろいろな方法でエロ画像をとってきたわけですが、取れないものも出てくるわけです。取れないわけじゃないんだけど、wgetでやるのは面倒なパターン。

wget -rで基本有効なのは同じサイトのHTMLや画像などになります。だからwww.hogehoge.comとかあった場合、wgetで再帰的にディレクトリを辿れても、画像がpic.hogehoge.comとかにあった場合、何も指定してあげなかったら取れないわけです。-Hオプションで他のドメインも許してあげて、-Dでその範囲のサーバを指定してあげるみたいにできるとは思いますが、pic1.hogehoge.com, pic2.hogehoge.comとか出てきたら面倒で、大体は網羅的に取れません(いきなりpic7.hogehoge.comとかでてくるかもしれないから)。

そんなわけで、ドメインが違ってもその画像だけ取ってくるものをGolangで作ってみました。とはいえ、参考のサイトのを取れただけで、みんな取れるようになったわけじゃないので、とりあえずはURLを放り込んでaタグでリンクされている画像については取れるものもあるという程度です。同じドメインにある画像も取れるようにしたかったんだけど、それはwgetでやってもらうことにして、違うドメインに貼ってあるリンクだけでも取れるようにしました。

package main

import (
    "github.com/PuerkitoBio/goquery"
    "fmt"
    "os"
    "path"
    "net/http"
    "io/ioutil"
    "strings"
    "net/url"
    "strconv"
)

func abspath(rpath string, urlstr string)(string){
  if(rpath[0] == '/'){
    u, _ := url.Parse(urlstr)
    return u.Scheme + "://" + u.Host + rpath
  }else if(strings.Contains(rpath, "http://")||strings.Contains(rpath, "https://")) {
    return rpath
  }else{
    dir, _ := path.Split(urlstr)
    return path.Join(dir, urlstr)
  }
}

func getfile( url string, dir string) {
  resp, _ := http.Get(url)
  defer resp.Body.Close()

  byteArray, _ := ioutil.ReadAll(resp.Body)
  ioutil.WriteFile("./" + dir + "/" + path.Base(url), byteArray, os.ModePerm)
}

func makedir()(string) {
    i := 0
    for ; i<10000; i++{
      _, err := os.Stat("./" + strconv.Itoa(i))
      if err == nil {
        continue
      }else{
        os.Mkdir(strconv.Itoa(i), 0777)
        break
      }
    }
    fmt.Println("mkdir:" + strconv.Itoa(i))
    return strconv.Itoa(i)
}

func main() {
    geturl := os.Args[1]
    fmt.Println(geturl)
    doc, err := goquery.NewDocument(geturl)
    if err != nil {
      fmt.Print("url scarapping failed")
      return
    }
    dirnum := makedir()
    doc.Find("a").Each(func(_ int, s *goquery.Selection) {
        dir, _ := s.Attr("href")
        if (strings.Contains(dir, ".jpg")||strings.Contains(dir,".png")||strings.Contains(dir,".gif")){
          fmt.Println(dir)
          absurl := abspath(dir, geturl)
          fmt.Println("absolute: " +absurl)
          getfile(absurl, dirnum)
        }
    })
}


もちろん適当に実験しながらだったんで、再帰的には動きません。あしからず。あとエラー処理もまともにしていません。コンパイルが通るか通らないかだけで、インデントや変数の名前とかも適当です。

使い方は$GOPATHを適当に設定して
go get github.com/PuerkitoBio/goquery
してあげて、上のソースをコンパイルするかgo runするかします。
引数に取りたいページのURLを取ってあげるだけでいいはずです。

実際動かすと、同ディレクトリに0から順番にフォルダができるので、そこに画像が格納されます。同じディレクトリでもよかったんだけど、1.jpg, 2.jpg…とかのぶち当たりそうな名前を処理するのが面倒だったので、ディレクトリを作ってそこに入れました。本人が使っての感想ですが、ちまちま取りに行かなくて済むのは楽です。ただ再帰的には動いてくれないので、サイト全部とかは無理です。本当はそこまでやりたいのだけれども、いろいろ処理を加えないといけないので、wget -rで取りにくいとわかっているところだけを取れるようにしました。

goqueryで楽できたけど、もう少し改良の余地はあるなぁと思いつつ、今回は終わり。

タグ:Golang
コメント(0) 
共通テーマ:パソコン・インターネット

久しぶりにRuby on Railsをやってみようと思ったのだけれど [プログラミング]

仕事で使うかもしれないということで、久しぶりにRuby on Railsをやってみようと思った。だけど、仕事場でWettyを使ってできないことに気づいた。すでに443番ポートをWettyで使ってしまっているからである。前に言った様にKDDIのおいたルータがヘボすぎて80番ポートを開けられない。不正アクセスが多すぎて、80番ポートを開けておくとルーターがフリーズしてしまうからだった。

そんなわけで、Webを使うRuby on Railsを使うことができないのでした。へ〜別にWebrickを3000番ポートとかで動かしているサンプルも多いから、それでいいじゃんと言う人もいるかもしれません。でも、会社のファイヤーウォールというか、プロキシが80番ポートと443番ポートの通信以外を通してくれないみたいなのです。通信の内容はどうあれ、接続先が80番とかじゃないとダメっぽい。試してないけどFTPとかは通るかもしれないけど、プロトコルの内容で止めている可能性もある。少なくともSSHは通らない。それが標準のポート番号なのか、プロトコルの内容なのかはわからない。

どっちにしてもWettyでHTTPSサーバを使ってしまっているので、使えるポートがなくて動作が見られなかったりする。遠隔でWeb以外につなぐ方法がないので、基本Webの開発はできなかったりする。今考えたんだけど、コマンドラインで動くWebブラウザをlocalhostで動かせばいいのではないかと思った。そういや、昔wgetとかSSHクライアントが良くわかってなくって、elinksとかを使った覚えがあった。当時はわけのわからないまま使っていたので、正直実用になる程使えたかどうかはわからないけれども、LynxとかLinksとかよりかは使いやすかった気はする。その当時は依存性の解決とか面倒だった気がする。そのくらい昔の話です。

よく考えるとRuby on Railsで実現できるレベルのGUIって、Elinksあたりでも再現できるんじゃなかろうかと思ったりした。というわけで、LXCでコンテナ作って、Ruby入れて、Rails入れて、PostgreSQL入れて、Elinks入れてやってみようと思う。正直、仕事中にそれをやっている余裕は今ないのだけれど、Wetty経由でもできなくはないかな。

最近はRailsの最新バージョンっていくらぐらいなんだろう。僕がガチでやっていた頃はver.3あたりだったのだけれど。

http://rubyonrails.org/
2017年3月20日でバージョン5.1.0rcって書いてある。僕が知っている頃から、内容が結構変わってそうだ。基本的なところは違わないんだろうけど。

チュートリアルの日本語版は無料で公開されていますね。英語で読むよりか吸収速度が違うので日本語の方がいいよね。
https://railstutorial.jp/

こんど環境を作ってみて簡単なものを作ってみようと思う。


これとか読むにつけ、Railsは手間を惜しむだけのものなのかなぁと

http://blog.sumyapp.com/2013/07/no-recommend-rails/
http://ledsun.hatenablog.com/entry/2013/07/24/112644

初心者にはわかりにくい、ということなんだけど、そういう論法はコンピュータにはありがちなんだよね。十分なブラックボックス化がされていないとか、デスクトップLinuxもそうだし。ちょっと問題が起こると必ずコマンドラインから修正しないといけなくなる。そしてわかっている多くの人はそれで乗り切ってしまう。だからWebを使いたいとか、Officeを使いたいだけの人にとってはあまりにも難解すぎる。正直、ファイラでGUIで辿っていける所を、cdでズンドコ進むと言うこと自体意味がわからないのもわからなくはないわけで。

RailsやるぐらいならPHPやれよというのはわからなくはないことだよね。実際素のPHPですむぐらいの規模が普通なんだろうし。Railsの問題はSQLをわからなくてもDBを使えちゃうってことなんだろうね。そこが便利な所なんだろうけど、結局得られたデータをお手軽に解析する場合は、SQLを叩くのが一番楽なんだよね。ExcelやAccessに落とすのも手だとは思うけど、ダンプするにもSQLを経ないといけないだろうし、やっぱりRubyもDBも手についていない状態で学ぶのは危険だと言えなくはない。

でも、自動車に例えると、エンジンの技術的な所を知らなくたって乗れるし、知らなくてはならないのは交通法規の方だったりする。エンジンなどが壊れた時には、整備工場に渡せばいいのだけれど、Railsというかそういうフレームワークに手を入れるのに、整備工場にあたる場所はないので自分でやるしかない。

それを言ったらそもそもRubyができているのはC言語だから、ソースから見ないといけないかと言われるとそうではないわけで、実際ソースを見ている人はRubyを使っている人としては少数派だろう。まぁありがたくそう言う人達の恩恵に預かっているわけだけれども、Railsになると自分で解決しないといけない部分も多くなると言うことなんだろう。あまりに簡単に雛形が作れてしまうところに問題があるんだろうけど、それはそれで便利でいいねでいいと思うんだけどね。苦労するときはいつか苦労するんだろうし。ただ、面倒がどちらが多いのかと言われると、基礎から自分で作ったほうがいいと言う論法もあると言う話で。

結局、どこまで作り付けのものを使うのか、と言うところであろうと思う。ものすごい専用の機械を使って、楽に高度なものを作るか、原始的なツールで手作業で作っていくか、というところでしょう。コンピュータで変わらない技術はないけれども、どれだけ潰しのきく技術を使うかというのは選択眼としては必要なものだろう。結局、必要な要件を無理のない技術で作っていくのが大事だってことなんでしょう。まぁそこいらの選択肢を選ぶのは難しいことだとは思うけど、RailsがFATで変わりやすすぎるのは困ったことですね。

PHPを使って素で作っていくことを考えると、困難が待ち構えていてもRailsを使おうと思う。どうせ内部でしか使わないシステムだろうから、バージョンが上がっても追随する必要もないし。ただ、できる人が少ないと改修とか面倒そうだな。自分がずっとそこにいられればいいのだけれど、基本的SEにそういうことは望めないし。

タグ:Rails
コメント(0) 
共通テーマ:パソコン・インターネット

基礎からやらないGo言語で、画像URLスクレイピング(失敗したけど続行) [プログラミング]

基礎ができていないのになんとなくGo言語を書いてみようコーナー。wgetが思うさま動いてくれないので、Golangのライブラリの機能を借りてやってみようという感じのもの。wgetをapt source wgetで取ってきて、html-parse.cを読もうとしたら長くてうんざりしたのでやめました。手直しするよりいちから違う言語でスクラッチしたほうが早い。

最終的にはページにある画像をみんな取ってくるという、どうにもけしからん目的。wgetで非常にとりにくいパターンがあるんだよね。wgetは再帰的にサイトを探ることが出来るんだけど、画像が別サイトにあったりすると採るのが非常に面倒になる。出来ないことはないんだけど、上手くいかないサイトのほうが多い。


Golangにはhtmlの標準パッケージがある。良く分からん。とりあえず、画像のURLをスクレイピングするHTMLファイルを取得したい。んでファイルに保存は出来た。
package main
import (
  "fmt"
  "net/http"
  "io/ioutil"
  "os"
)

func main() {
  url := "http://google.com"
  resp, _ := http.Get(url)
  defer resp.Body.Close()
 
  byteArray, _ := ioutil.ReadAll(resp.Body)
  fmt.Println(string(byteArray))
  ioutil.WriteFile("./test.txt", byteArray, os.ModePerm)
}

必ずしも保存する必要はないけれども、このファイルを解析すればいいわけだ。htmlパッケージを使えるのかな。あんまり探して見てないけど。


スクレイピングするのにはもっと簡単な方法があって、既存のパッケージにお任せで。
http://qiita.com/ryurock/items/b0466ad144f5e0555a95
を少し変えればimg src="ごにょごにょ"
がすぐに取れる
package main
import (
    "github.com/PuerkitoBio/goquery"
    "fmt"
    "os"
)
func main() {
    fmt.Println(os.Args[1])
    doc, err := goquery.NewDocument(os.Args[1])
    if err != nil {
        fmt.Print("url scarapping failed")
    }
    doc.Find("img").Each(func(_ int, s *goquery.Selection) {
          url, _ := s.Attr("src")
          fmt.Println(url)
    })
}


引数にURLを与えると出てくるのは出てくるのだが、きょうびimgで表示させているパターンってのは少ないらしい。何だよそれw。そんなんでブラウザから表示されている画像を指定してあげるような方法じゃないと、ソースから解析してとかかなり面倒な感じ。


ということで、他の言語でも単体での画像クローリングはやめました。それって画像だけに限ってだけどブラウザ作るのと大して変わらんやんという事なので。ちょっと視点を変えてFirefoxのプラグインとして作ってみる。どうせURLとる時にブラウザ使うわけだし。

でも、一ページでaタグで別ドメインに張ってあるような画像のページはわりと楽にできそうなので、後で少し考えてみる。まぁ二つのサンプルファイルをつなげればできそうな感じだが、テキストファイルしかまだ保存していないので画像のバイナリを扱えれば問題ないだろう。それにgoで作っているからWindowsでもOKだろうし、Bash on Windowsで動かしてもいいわけで。wget -rのような再帰的動作をさせられれば、気軽にエロ画像を得られるわけで。というか、手動でやれば済むことをいちいちコードにしたがる馬鹿がここにおるw

コメント(0) 
共通テーマ:パソコン・インターネット

WettyでつないでLXCで環境作ってどうしよう。 [プログラミング]

久しぶりにUbuntuでLXCを使っている。結構色々忘れてしまっているのだが、逐一覚えているようなものでもないので、自分のブログの覚書を見ればいいのだけれど、結局ググって最初からやり直しな感じ。

wetty経由で操作しているのだが、マウスオペレーションでコピペできないなと思っていたら、Ctrl+C, Ctrl+Vが使えたりしたので楽ができている。マウスでのコピペを出来るように実装しようかと思っちゃったよ。実際、xterm.jsを使った簡単な実装を見てしまったので、間違ってそっちのほうに行っちゃわなくてよかった。

UbuntuにUbuntuコンテナを使うと言うつまらない使い方なのだが、やはり使い慣れたディストロを使うのが面倒がなくていい。どうせ使い捨てなんだから、LTSとか守りに入っていないで最新バージョンを使えばいいのだけれども、なぜか踏み込めないヘタレ根性なのでした。

そうそう
lxc exec container-name /bin/bash
で入るんだったっけかな。
/bin/bashはbashのみでも可能な模様。

んで、16.04を入れたんだけど.2が入っていて最新でほとんどapt update && apt upgradeしないで済んだ。前は一番最初にガッツリ入れられた気がしたんだけど、リポジトリが最新になっているみたい。CanonicalもLXCに本腰になってきたというわけだ。


Python3を入れようと専用のコンテナを作ろうとしたのだけれど、デフォルトの環境に入っていました。Pythonも出世したものです。前はLLとしてRubyとどっこいどっこいだったけど、Googleが使い出して、機械学習でやたら使われるようになってから一気にメインストリームに上り詰めちゃった感じです。それにしてもPython2系がのさばっていたので、3系統に一本化できそうで良い傾向。

んで特にバージョンを気にするわけでもないので、Pythonはそのままでいいことにしました。Python2.xじゃないからいいやと言うくらいのもので。Pythonで何かをしたいと言うわけでもない気はするのだけれど、一応はディープラーニングで使えればいいなと思ってはいる。pyenvとか入れないで済んじゃったし、後はしこしこ勉強するだけだよね。



これはWettyじゃなくてLXCの問題かもしれないけど、コンテナを作ってユーザーを作ってsudoの設定をして使おうとしたら怒られた。
sudo: no tty present and no askpass program specified

結局、.bashrcに
alias sudo='sudo -S'
として設定して避けたのだが、sshのコマンドで逃げてもいいんだよね。pty.spawnのところのパラメーター設定を直すのが筋なんじゃないかと思ったり。


Pythonで勉強しようとは思っているけれども、Webがwettyで443ポートをふさがれているので、基本使えないんだよね。80番ががっつり空いてるやん、と言われればそうなんだけど、KDDIが配布しているルーターが非常に貧弱で、80番ポートを開けておくと数週間でルーターがハングする。あまりに受付する接続が多いのでフリーズしてしまうらしい。

というか、KDDIもそんな貧弱なルーターよこすなよな。KDDIがIP電話付けたいだけがために、しょっぼいルーターを使う事を強いられてるわけで。まぁ普通の人は意図的に80番ポートなんて開けないけど、営業の人がルーターを変えたい場合は応相談だって言っていたな、口から出まかせかもしれないけど。

80番ポートのアクセスログを見たことがない人は知らないかもしれないが、やたらと色々なところからアクセスが来る。他のポートにも不正なアクセスがあるわけだが、80番ポートはずば抜けて多い。一番開いている可能性が高いのか、脆弱性の高いアプリが待ち受けていることが多いのか、前に見た時は多かった覚えがある。それに比較すると443ポートは元々セキュアな通信をするという意図があるので、そこいらの意識的な高さがクラックを遠ざけているのかもしれない。ともあれ、そのほとんどはボットなどのアクセスだろうから、基本的なところを押さえておけば大丈夫。基本的に特定の脆弱性を狙っているから、穴のある機器やアプリを使っていない限りは大体大丈夫なはずなんだが。大丈夫なことを願うw。少なくともリポジトリからとれるソフトを使っている限りは最新にしておけば問題ないでしょう。


さてPython3で何しよう。Web以外ってことだけでかなり限られてくるよなぁ。今は機械学習とかPythonで流行っているけど、それだけのマシンパワーがなかったりするサーバだし。とりあえずPythonの文法を学びたいけど、何か目的がないと学びにくいのも確か。x16のスロットにGeForce入れてPythonでCUDAとかもいいな。ディープラーニングもやらずじまいだし。

そういやGolangもやってない。結構突っ込んでやろうと思っていたんだけど、いつもと同じフェイドアウトでグダグダである。でも、Go言語だったら別にWeb関係じゃなくてもやることありそうな気がするね。というか、コンパイルして速度を出したい目的とか、いろんなプラットフォームに持っていきたい場合とか使えるんだよなぁ。具体的に何やりたいか思いつかないけど。Go言語でGPGPUとかできるんかな。Pythonでできるんだからできそうな気もするけど、実際はどうなんだろう。CUDA自体が対応していた気もするが忘れた。GPGPUは面倒過ぎて見放したし。

ん~今見てきたらMini-ITXのサーバのマザーボードにはx16のスロットがなかった。x2だかx4のしかなかった。同じMini-ITXのマシンにはx16スロットが一つあるんだけど、それだと今の省電力マシンでのサーバ運用ができなくなってしまう。x16スロット使用となるとそれなりに電力消費も大きくなるし、電源も普通のATX電源を使わないといけなくなる。そうなると安定運用もできなくなる。

デスクトップ電源よりACアダプタでの給電の方が安定しているみたいなんだよね。その代わり、出力は半減以下になるわけだけど。ずっとスリープ状態でデスクトップを運用していてやっとデスクトップ電源の脆弱さが分かった。Pixivのインフラ担当の人が言っていた気がするんだけど、一番電源が壊れやすいというのは連続運用という点では間違っていない。ちょこちょこ立ち上げなおすパソコンだとHDDのクラッシュの方が目立つんだろうけど、電源は休ませないとすぐヘタるっぽい。ACアダプタも電解コンデンサとか使ってるのになぁ。なんでか分からんがそこのところは仕事も勉強もしていないので知識的に闇の部分です。


というわけでGPGPUはできない。既存のプログラムの高速化とかは無理だな。お手軽にできることって結構掘りつくされていて、自分が入り込む余地ってないのかもしれないなって思ったり。何か楽しい事ってないかなぁ。本当にゴリゴリやるなら開発環境自体に参加するとかあるのだが、それは自分には荷が重すぎる。ともあれ、LinuxでCUIのみでできることって個人的に興味を引く分野から遠いんだよね。基本、WindowsのGUIのアプリを作りたいと思って入ったクチだから、正直Linuxのツールが何とかとかあまり得意ではない。ツールを外から使うならさんざんっぱらやったから普通の人程度にはできるけど、C言語で一からスクラッチしたとかautoconfを使うようなことをしたことがあまりないんだよね。仕事でもとりあえずmakeファイルで自分のところで動けばいい的な事しかなかったし。

まぁぼちぼち気になるところをやっていければと思う。まずは久しぶりにC言語回り。Go言語にLLVMあたりかな。あとWindows系の技術を持っていきたい。まぁ大体大規模か必要じゃないもの以外は軒並み移植されてたりするから気にする必要はないのかもしれないけど。

コメント(0) 
共通テーマ:パソコン・インターネット

Swift3でアプリケーションバンドルの中の、埋め込みコマンドを探して実行する。 [プログラミング]

Macでコマンドラインアプリケーションをラップして、GUIで使いたいとか思いません? でも、配る時にコマンドラインツールをHomeBrewで入れてね、というのはスマートじゃないですよね。だからHomeBrewで入れたツールのバイナリを奪ってきて、Xcodeで作るGUIな.appの中にぶち込もうという計画。

わかっている人にはそんなに難しいことではないのだろうけど、アプリケーションバンドルって何?から始めようとするとキツい案件になる。でも、コマンドを打ちたくないから安易にできるようになった方がいいんですよねって話だし、そう考えるのはものぐさか、コマンドラインの初心者だと思うんだよね。だから、できるという状態まで持って行ってあげようというのが趣旨です。


それまでライブラリを.appの中にコピーして使ったということはあった。mailpeeper-tlsではOpenSSLの.dylibを使っていたので、そこいらのところはObjective-Cで習得済みだった。基本的にXcodeの操作なのですが、MacPortsなりHomeBrewなりで生成できるバイナリのライブラリをもってきて、実行時にリンクさせるようにするのでした。今回はリンク話の直パスということになります。

今回はSwiftで独立したバイナリのコマンドラインアプリケーションをコピーしてきて、そのバイナリを実行しようというものです。基本的に次のことができればいい。

・バイナリを.app内に取り込む。
・.app内のバイナリの位置を特定して実行する。

この二つだけで大体問題は解決します。やってみたらそんなに難しくなかった。今回は例えばgitを使いたいなと思います。そもそもGitなんて使えんのかいなということなんだけど、実際Xcodeでも使っているので問題ないと思ったのです。

Xcode.appのバンドルの中を検索してみると
/Applications/Xcode.app/Contents/Developer/usr/libexec/git-core/git
にあることがわかります。別にソースごとXcodeの中に埋め込んでいるわけではなく、独立したコマンドのバイナリが入っているのですね。これには少しホッとしました。

ただリソースの場所としてはずいぶん自由な場所に入れてあるので、探すのが面倒になりそうだなと思っていたら最終的にはそんな気苦労は無用でした。そういうのを前提に関数が用意されているので、結構自由にバンドルの中に放り込むことができそうです。




さて実際にやっていきましょうか。最初にバイナリをバンドルの中に入れ込むのですが、HomeBrewから入れ込むにしろ、他のツールから入れ込むにしろ、whichコマンドで場所を特定してコピーしていきます。自分で作ったツールで./a.outして使ってたら直接でいいですなんて説明はいいですよね。とにかくプロジェクトのフォルダーにコピってきます。

そしてXcodeのProject Navigatorに突っ込んでおきます。どこでもいいです。とりあえず取り込むために登録するだけなので、gitに登録できるような状態にしておけばいいです。今回はgitコマンドなのでgitにgitを登録するような感じになりますがややこしいのは置いといて。こんな感じ。GUIでFinderからドロップするだけでもよかったかな。とにかく登録する。

pngit.png

Productsじゃないだろと言うツッコミはさておきw、実際はProductsにも入ってないノンカテゴリのフォルダなしだったりします。普通はこういう適当なことはやめておきましょうw。でもできることは確かです。


.appの中に入れるのはいくつか方法はあると思いますが、Projectの設定のBuildPhasesのCopy Bundle Resourcesに入れてしまうのが面倒がないと思います。苦労して入れたい方は他にも方法があると思うので探してやってみてください。実際Xcodeでやっているからできると思います。昔はcpコマンドとかを埋めてコピーしていた気がします。今回はとりあえずリソースとして入れこんでみることにします。

copybundle.png

実際にはこういう風にコピーされているのを確認することができる。

innnerbundle.png

まぁ探してくれはするのでどこでもいいのですが…。


さて実際のサンプルソースを見てみましょう。

ほぼ
https://gist.github.com/Seasons7/836d3676884a40c8c98a
なんですが、ちとふるいので少し改変しないと動きません(NSBundleとかがBundleになっていたり)。でもコンパイラが指事してくれるから問題ないです。

今回は前にやったディレクトリを取ってきた部分と絡めて実装する。ボタンとか押すと発動するようにしてみてください(実際そうしてる)。

@IBAction func addGit(_ sender: Any) -> Void {
	//フォルダ指定
	let openPanel = NSOpenPanel()
	openPanel.canChooseDirectories = true	// ディレクトリを選択
	openPanel.canCreateDirectories = false	// ディレクトリを作成できない
	openPanel.canChooseFiles = false		// ファイルを選択できない
	
	var path :String=""
	
	let num = openPanel.runModal()
	if num == NSFileHandlingPanelOKButton{
		for fileURL in openPanel.urls {
			let filePath = fileURL.path
			path = filePath
		}
		//下のコマンド呼んでる。実際にgitを発動しておる
		callGitCommand(path, "init")
		
	}else if num == NSFileHandlingPanelCancelButton{
		NSLog("Canceled")
		return
	}
}

func callGitCommand (_ path :String , _ param :String){
	let task = Process()
	let pipe = Pipe()
	
	task.launchPath = Bundle.main.path(forResource: "git", ofType: nil)
	task.arguments = ["-C", "\(path)", "\(param)" ]
	task.standardOutput = pipe
	task.launch()
	
	let handle = pipe.fileHandleForReading
	let data = handle.readDataToEndOfFile()
	let result_s = String(data: data, encoding: String.Encoding.utf8)
	NSLog(result_s!)
}


冗長なところとコメントはいらないから消したつもりなんだけど残ってるかな。あっても許してね、一応動くし。

http://d.hatena.ne.jp/Watson/20100324/1269427861
のように、NSTask関係では、コマンドラインは相対パスだと動かないから、
/bin/sh -c をかますといいとありますが、結局

Bundle.main.path(forResource: "git", ofType: nil)

でフルパスというか絶対パスが出てきてしまうので気にしないでいいです。パラメータに渡すパスとかも絶対パスを渡せば動作的に問題ないです。

パスのところは空白文字が入るとダメかもしれないので、ダブルクォーテーションとかで括ったほうがいいのかもしれません。そこいらへん試してないけど、一応日本語パスとかもいけたんで大丈夫かもしれません。というか、それくらいテストしろw。そういう面倒が嫌なので、そもそも空白文字のあるディレクトリは作らないようにしているんですけどね。

とにかく、.appの中に入れ込んだコマンドラインアプリケーションでも実行することができたのでした。しかし、実行環境が必要な場合もあると思うので、その場合はそれも持ってきて実行パスとかに置かないといけないのかもしれないなと思ったり。というかgitだってHomeBrewがない環境で動くかどうかって試してないから、HomeBrewのコンパイルリンクの方法が別のライブラリに頼っていた場合は、それも一緒に持ってこないとダメだよなぁ。少なくとも依存パッケージを入れられた場合は、それらは必要となるから結構面倒な話になるかもしれない。

ということを気にするとHomeBrewがない環境が必要になっちゃうじゃないか。面倒くさいなぁもう。

タグ:Swift3
コメント(0) 
共通テーマ:パソコン・インターネット

Swift3でNSOpenPanelをmodalで開く [プログラミング]

時間ねーので適当だが動くでしょう。前回はモードレスなダイアログだったので、いろいろ問題がある人はあるんでしょうから、今度はモーダル。

それにクロージャ(たぶん)の中に、処理をゴリゴリたくさん書いていくのも綺麗じゃないし、外出しするとなんかよくわかんねーエラーが出てたのでやめた。
Call to method 'なんとか' in closure requires explicit 'self.' to make capture semantics explicit
とか
Missing argument label 'file:なんとか' in call cloursure
とかな。めんどうくさいので。

以下前回。

http://miff.blog.so-net.ne.jp/2017-02-08-2

今回はAppleへの文句は垂れない予定。
以下サンプルソース。部分的だが許して。大体必要なものはあると思うし。

	let openPanel = NSOpenPanel()
	openPanel.canChooseDirectories = true	// ディレクトリを選択
	openPanel.canCreateDirectories = false	// ディレクトリを作成できない
	openPanel.canChooseFiles = false		// ファイルを選択できない
	
	let num = openPanel.runModal()
	if num == NSFileHandlingPanelOKButton{
		for fileURL in openPanel.urls {
			let filePath = fileURL.path
		}
		NSLog(filePath)
		
	}else if num == NSFileHandlingPanelCancelButton{
		NSLog("Canceled")
		return
	}

これでファイルパスは取れるでしょう。取れなかったらSo-netのアカウントとって下のコメントで聞いてくんな。わかんねーかもしれないけどな。




そんで欲しいディレクトリをほげほげしたいわけだが、
directoryHogehoge(filePath)

NSLog(filePath)
あたりに置くのだけれど、関数の宣言がちと気持ち悪い。どういう意味があるのかわからないのだけれど

func directoryHogehoge (_ path :String){
}

となぜかアンダーバーを置かないといけないみたいだ。なんだろう。ボタンとかをつなげて作ってくれる自動的にできるソースも
@IBAction internal func hogehoge(_ sender: Any)
みたいに_がついてる。

ここで登場

もっとスマートな音楽の埋め方はないのかw
IMG_4586.JPG
買っちゃいました。アマゾンは本は昔と同じ送料無料だったのね。
にしても地面がきたねーなおい。ブツ撮りは背景が綺麗じゃないと話にならないけどこの際気にしないw


この本のP.109に外部引数名と内部引数名があって、外部引数名を省略するときにアンダーバーを付ける、と。
func hoge(naibu1: Int, gaibu naibu2: Int)
ってこんな感じで。第一引数は外部も内部も兼用、かな。

呼ぶ時には
hoge(naibu1: 5, gaibu:6 )
みたいによく見かける key:value な感じの書き方になるようです。

ややこしいことに、二つ目の外部引数を付ける時は、一つ目の外部引数は省略可能。第一引数の省略を省略しないで書くと

func hoge(_ naibu1: Int, _ naibu2: Int)

と書けて
hoge(1, 2)
とできる。まぁ普通だよね。C言語っぽいよね。どうせなら第一引数も名前使った方が気持ちよかろうにと思うんだけど…。そこいらはObjective-Cに習ったんだろうか。互換性をつけるために。

下記のコードをPlayGroundとかで実行すると、まぁそうだよね、という無駄な「1+2=3」が計算できる。

//よくある第一外部引数省略バージョン
func hoge(naibu1: Int, gaibu naibu2: Int){
	print( "\(naibu1) + \(naibu2) = \(naibu1 + naibu2)" )
}

//両方とも省略して、C言語っぽい呼び方をできるバージョン
func hogehoge(_ naibu1: Int,  _ naibu2: Int){
	print( "\(naibu1) + \(naibu2) = \(naibu1 + naibu2)" )
}

//どうせなら第一引数から全部やった方が気持ちよかろうバージョン
func hogehogehoge(gaibu1 naibu1: Int, gaibu2 naibu2: Int){
	print( "\(naibu1) + \(naibu2) = \(naibu1 + naibu2)" )
}

hoge(naibu1:1, gaibu:2)

hogehoge(1,2)

hogehogehoge(gaibu1:1, gaibu2:2)

何が言いたいかと言うと、初めの引数がなんとなく気持ち悪いってこと。でも、多くの人がそう書くだろうから無駄に混乱しないようにと言う話。たぶんこれはObjective-Cのオブジェクト指向部分の書き方が悪いんだろうと思われ。Obj-C動くようにしか書いてないから、実際は違うかもしれないけど。


ありがとう、本よ! Webがあっても本で得られる滋養って違うものがあるよね。

Swift実践入門 ── 直感的な文法と安全性を兼ね備えた言語 (WEB+DB PRESS plus)

Swift実践入門 ── 直感的な文法と安全性を兼ね備えた言語 (WEB+DB PRESS plus)

  • 作者: 石川 洋資
  • 出版社/メーカー: 技術評論社
  • 発売日: 2017/02/07
  • メディア: 単行本(ソフトカバー)


この本はかなり硬派です。すぐにSwiftでアプリを書きたいって人には向いてません。

タグ:Swift3
コメント(0) 
共通テーマ:パソコン・インターネット

Swiftのサンプルコードがさっぱり動かない(NSOpenPanel) [プログラミング]

動かないどころか、コンパイルさえ通らない。最終的には動かしたんだが…。

Swift自体とライブラリ変えすぎなんじゃない?
半年前のサンプルソースが動かないとかどうかしてるよ。アップルらしいといえばApple純正ソフトらしいけどw。


Swiftの文法に近づけようとしすぎて、CocoaとかのObjective-Cの関数などの名前からも乖離している。ちょっと頭がおかしいのではないか。

Xcodeも勝手にコンパイルしてくれるので、ガタガタして落ち着かない。すごく気持ち悪い。Obj-Cでもここまでおかしくなかったぞ。そもそもの文法が分かっていないのも問題だけど、その程度は大体はサンプルソースを見ながらだったら普通はいける。コンパイラのエラーで大体わかる。だけど何が悪いか見当がつかない。

Obj-Cではdeprecatedなものでも動いてくれはするが、Swiftではもはやコンパイルすら通してくれない。静的言語としてはこれくらいで当然なのかもしれないけど、Obj-Cよりはサクサク書けるものだと思っていた。ちょっとこれはひどくないか。他の言語を渡り歩いてきたけど、Webのサンプルソースさえ少しの手直しで動かない言語ってなかなかないぞ。

NSOpenPanel.begin(completionHandler:)
がやっと動いた。ほぼスケルトン状態にしてやっと文法的に正しくなった。
もともと、どこかから奪ってきたソースがbeginWithCompletionHandler()だったから、ちょっと変えるだけだったけど、何でこんなにも問題が起こるのかわからないくらい他のところでエラーが出て今はコメントアウトしている。


問題はXcode8でSwift3に変わっているらしいこと。
 https://developer.apple.com/swift/blog/?id=36
具体的な内容は
 http://artteknika.hatenablog.com/entry/2016/11/01/192942

「Swift側の標準ライブラリ(?)に即したような形で、ライブラリの変更が行われている」+「文法の変更、又は廃止」。廃止されると全く通らなくなるので困るね。というか、よく考えられた言語だと、バージョン間の変更も穏やかなんだけど、クソみたいにみんなが集まってきちゃうと、Python2.6, 2.7, 3系統みたいな状態になってしまうってことだろう。賢い人ばかりだといいけど、そうじゃないのが世の常。


とりあえず何もできないけど、ディレクトリ選択ダイアログだけは出るぜな状態。Swiftの文法何もわかってやしない感じw。これからこれから♪ 少なくともObjective-Cの機能は別の書き方で残っているはずだ。
	let openPanel = NSOpenPanel()
	openPanel.canChooseDirectories = true // ディレクトリを選択
	openPanel.canCreateDirectories = false // ディレクトリを作成できない
	openPanel.canChooseFiles = false // ファイルを選択できない
	
	openPanel.begin(completionHandler: { (num) -> Void in
		if num == NSModalResponseOK {
			NSLog("Open")
		} else if num == NSModalResponseCancel {
			NSLog("Canceled")
		}
	})

もしかするとXcode9ぐらいには動かなくなってるかもねw。でも、一応8.2で動くはず。というか動いている。



よし、最後までやってディレクトリを取ってみましょうか。NSLogにパス吐き出すだけですけど。NSURL関係も変わってしまっているらしいな。あぁ面倒くさぁ。

	openPanel.begin(completionHandler: { (num) -> Void in
		if num == NSModalResponseOK {
			for fileURL in openPanel.urls {
				let filePath :String! = fileURL.path
//					let decoadedPath :String! = filePath.stringByRemovingPercentEncoding  // 日本語ファイルの場合
				NSLog(filePath)
			}
		} else if num == NSModalResponseCancel {
			NSLog("Canceled")
		}
	})

元々のソースには日本語パスのデコードがあったのだけれど、最近はUTF-8とかで管理されているだろうから気にする必要がなさそうな気がするんだけどね。ともあれ、システムの日本語表示されるディレクトリは英語の代替文字があったりする。というか、日本語の方が代替文字なんでしょう。「デスクトップ」とか。

あと複数ファイルを選択してないから、for inで回す必要はないのかな。あとファイルパスはletにする必要があるのだろうか。普通に考えるとvarとかだよな。いまいちSwiftの常識がわかってない。


とりあえず、エラーの傾向はわかった。変数が使われない時はワーニングを吐く。これは最近のコンパイラの常識なのかな。昔はモノによって出たり出なかったりしてたけど。あとdeprecatedな関数はコンパイルエラーが出て、代替関数が提示されるので変えるしかなさそう。

Obj-Cとかやたら古いdeprecatedな関数でも使えたりするんだけど、そういう保証しませんという立場から、放棄するから使えませんに変わっていくのかな。まぁ変な挙動がなくなるのはいいかもしれないけど、環境を変えるごとにコンパイルエラーとかを吐かれたんじゃたまったものではない。まだワーニング程度ならまだしも。それもApple側のつまらない細かい変更に対応しろということなんだろうな。どんどんAppleの開発者のエゴが反映されていく。そんなの一般的な開発者の方は望んじゃいないんだよ。Obj-Cのライブラリの運営が今よりまともだったのは、NeXT社のエンジニアが入っていたからじゃないかなと思わせる。

ともあれ、基本的にシステムに近いAPIはdeprecatedにすべきものではないという事はMicrosoftの技術者でさえ少しはわかっている。まだライブラリのバージョンというか名称を変えてしまうぐらいのものだとしたら別に仕方ないと思うけれどそうじゃないもんなぁ。Xcodeを初期から見ているものとしては暗雲立ち込めているとしか見えないんだがw。まぁSwiftのライブラリと言語仕様が固まるまで待つしかないのかもしれない。


よく「もうObj-Cなんて古いからSwiftでしょ」なんて文句を聞くんだけど、この状況を見るとObj-C + ARCを使っている方がずっとマシなような気がする。少なくとも長期間アプリに手を入れていくことを考えるとSwiftは最適な解では決してない。そのところをわかっている人はSwiftを諸手を挙げて賞賛するわけがない。

だけど、Swift自体が悪い言語というわけではなく、単にAppleのライブラリ作成のお行儀が悪いだけ、Xcodeが無遠慮なだけという話だ。だから晴れてOSSになって、AppleごとSwiftが沈没する危険は回避されたという喜ばしい状況にはなってはいるのだから、暗いだけの話ではないのだろう。

タグ:Swift3
コメント(1) 
共通テーマ:パソコン・インターネット

今度はSwiftででもアプリを作ってみるかぁ [プログラミング]

mailpeeper-tlsのリリースも終わり、特に文句もきてないから誰も使ってないか、問題がなかったのでしょう。久々にObjective-Cをいじって、わかりやすいけど面倒臭いなというのが本音だったりする。そもそもretainしたり、releaseしたりするのが面倒なんじゃぁというところが今時ではない。まぁARCに対応した文法にすればいいのだろうけど、下手にいじって挙動を壊すのも何なので。

一応まだMacは使うつもりなので、Swiftぐらい空で書けるようにしておこうかなぁと思ったり。

Swift実践入門 ── 直感的な文法と安全性を兼ね備えた言語 (WEB+DB PRESS plus)

Swift実践入門 ── 直感的な文法と安全性を兼ね備えた言語 (WEB+DB PRESS plus)

  • 作者: 石川 洋資
  • 出版社/メーカー: 技術評論社
  • 発売日: 2017/02/07
  • メディア: 単行本(ソフトカバー)


巷に出回るiOSに焦点を絞ったアプリ本じゃなさそうで、きっちり文法を学べそうだ。それに技評ってのもポイント高い。そういやWEB+DB PRESSとか買ってないなぁ。暇がなくて読めないし、買う余裕がないので手にもしていない。Amazonで買うぐらいなら定期購読しちゃった方がいいと思うし、そこまで体が欲していないのも事実。

今はググればアプリに必要な情報はつぎはぎにでも手に入れられるし、そもそもプラットフォームのAPIをつぎはぎにして作るのが大体のアプリだったりするので、規範となる文法書はあった方がいい。その瞬間しか役に立たないアプリ作成の本はいらんのだよ。

とりあえず、GitのGUIラッパーを作りたいなと思っている。だってgitコマンド面倒なんだもん。Xcodeみたいにお気楽にやりたいじゃん。でも、Xcode以外でgitを使おうとすると途端にチート表と首っ引きになってしまう。正直、本来のコーディングの知識だけで頭がいっぱい。だから、与えられたメニューだけでお手軽に使えてしまうものを作りたいのだった。もうすでにあるのかもしれないけど、僕が探した時にはMacでは中途半端なものしか存在しなかった。

とはいえ、ちょっと高いなぁという気はしている。売れないのを見越して高値に設定している? それともそもそも分厚さがあるとか。どちらにしても技術書としても安い部類の本ではない。やっぱりマイナーな本はそれなりに高くなっちゃうんだよね。

まだ本を売るまでに時間があるから簡単な雛形をSwiftで作ってみようかな。どうせObj-Cに毛が生えたような書き方しかできないと思うけど。

タグ:Swift3
コメント(0) 
共通テーマ:パソコン・インターネット

なぜAppleはObjective-Cを選んだのか。 [プログラミング]

会社で無理やりObjective-Cやらされてウゼェとか思っている人もいるんでしょうが、まぁSwiftとか出たからいいじゃないですか。言語としてはまだまだひよっこだけど、いろんないいところを受け継いでいるのは間違いないところで、これからOSSになってどう羽ばたくのかは未知数だったりします。

にしてもObjective-CによってAppleは結果的に救われたことになっています。途中でGC入れたり、ARCに変わったり、いろいろ変遷を経てきていますが、Swiftも加わることで使いやすくはなってきています。少なくともOSX当時のObj-Cよりかはマシにはなっているはずです。

ともあれ、何でObjective-Cなんてマイナーだった言語を使い出したのかという話です。それはそもそもOSXの元になったNeXT STEPで開発言語をObjective-Cを使っていたからだといいます。NeXTは使ったことはないのだけれど、初めのXcodeの大盤振る舞いでNeXTで使っていたのかぁと何となく思っていました。

基本的にWebObjectsとかでJavaを使っていた関係で、Obj-CとJavaが混在する形の開発環境になっていたと思う。CocoaなんかもJavaから使えた。何でJavaを捨てたかはいろいろあるんだろうけど、そもそもWebObjectsが普及しなかったということなんだろう。一時期はAppleも企業向けにアピールしていた時期があって、Xserveとかのハードウェア製品もあったのだけれど、ずいぶん前に完全撤退してしまった。サーバハードウェアの技術はMac Proに引き継がれたけれど、今は新しいCPUにもされず放置されている状態。正直、どうでもいいと思っているのでしょう。ゴミ箱同然なわけですw。

それと多分Javaのライセンスがうざかったということもあるのでしょう。Appleは今はLLVMでブイブイ言わせてますが(表現が古いw)、それもgccがウザかったからということなんだろうなと推測されます。要するにGPLがウザかったということなんでしょうね。それでLLVMにお金を投じるようになったみたいです。それと同様にSunのJava縛りが面倒でならなかったのでしょう。だからJavaのサポートを止めてしまった。それは開発の上でも動作環境としてもです。そんなリソース割いてられっかということで。

それと思ったよりか開発者がObj-Cに付いてきてくれたというのもあるんじゃないかなと思う。C++よりかは複雑怪奇になっていないし、メモリの解放さえきちんとやっていれば、C言語の建て増し(ちょっと異質感は否めないが)なのでそんなに難しいこともないわけで。オブジェクト指向としてもプレーンだったし、Xcodeの出来もそんなに悪いものではなかったのも一因だろうと思う。


AndroidではJavaの言語仕様を使ったPureじゃないJavaを使っていて、Sunの後釜のOracleから訴えられているわけですが、それも何とかならないかなぁと思ってしまいます。いつまでもJavaを離さないというのも言語としてどうかと思うのですよ。ビジネス使いとしては、一企業がサポートしてくれる安心感というのもあるのでしょうが、正直OSSが一般的な時代としてはプロプライエタリと言われても仕方ない感じはします。Oracleになってからは特に面倒臭いなぁという感じが増しています。というかオラクルが嫌いなだけだったりしますが。

で、iPhoneがメモリが少なくて済んでいるのも、ネイティブバイナリで動いてガベージコレクションを使わないObj-Cの賜物なのですよね。iOSでもJavaを使っていたら多分Androidと同じスペックじゃないと同程度の性能を発揮できなかったんだろうなと思います。そして、面倒なライセンスの回避もできたわけですし、わざわざ変態みたいにObj-Cを引っ張り出してきた意味があったわけですよね。


AppleはObj-Cを選んだというより、OSXを作るにあたって必要だったし、そのあと他の言語にマイグレーションするような状態でもなかったというだけだったりします。まぁ素のC言語よりかはマシでしょう。少なくてもオブジェクト指向万歳な世代は過ぎ去ったとはいえ、オブジェクト指向自体が当たり前になっているところもあるわけですし、これから先もAppleというメジャーマイノリティの中で使われ続けることになりそうです。今すぐにSwift代替というわけにはいきませんしね、互換性が多少あるとはいえ。


コメント(0) 
共通テーマ:パソコン・インターネット
前の10件 | 次の10件 プログラミング ブログトップ